MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
dict0crea.cc
Go to the documentation of this file.
1 /*****************************************************************************
2 
3 Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
4 
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.
8 
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.
12 
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.,
15 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
16 
17 *****************************************************************************/
18 
19 /**************************************************/
26 #include "dict0crea.h"
27 
28 #ifdef UNIV_NONINL
29 #include "dict0crea.ic"
30 #endif
31 
32 #include "btr0pcur.h"
33 #include "btr0btr.h"
34 #include "page0page.h"
35 #include "mach0data.h"
36 #include "dict0boot.h"
37 #include "dict0dict.h"
38 #include "que0que.h"
39 #include "row0ins.h"
40 #include "row0mysql.h"
41 #include "pars0pars.h"
42 #include "trx0roll.h"
43 #include "usr0sess.h"
44 #include "ut0vec.h"
45 #include "dict0priv.h"
46 #include "fts0priv.h"
47 #include "ha_prototypes.h"
48 
49 /*****************************************************************/
53 static
54 dtuple_t*
55 dict_create_sys_tables_tuple(
56 /*=========================*/
57  const dict_table_t* table,
58  mem_heap_t* heap)
61 {
62  dict_table_t* sys_tables;
63  dtuple_t* entry;
64  dfield_t* dfield;
65  byte* ptr;
66  ulint type;
67 
68  ut_ad(table);
69  ut_ad(heap);
70 
71  sys_tables = dict_sys->sys_tables;
72 
73  entry = dtuple_create(heap, 8 + DATA_N_SYS_COLS);
74 
75  dict_table_copy_types(entry, sys_tables);
76 
77  /* 0: NAME -----------------------------*/
78  dfield = dtuple_get_nth_field(
79  entry, DICT_COL__SYS_TABLES__NAME);
80 
81  dfield_set_data(dfield, table->name, ut_strlen(table->name));
82 
83  /* 1: DB_TRX_ID added later */
84  /* 2: DB_ROLL_PTR added later */
85  /* 3: ID -------------------------------*/
86  dfield = dtuple_get_nth_field(
87  entry, DICT_COL__SYS_TABLES__ID);
88 
89  ptr = static_cast<byte*>(mem_heap_alloc(heap, 8));
90  mach_write_to_8(ptr, table->id);
91 
92  dfield_set_data(dfield, ptr, 8);
93 
94  /* 4: N_COLS ---------------------------*/
95  dfield = dtuple_get_nth_field(
96  entry, DICT_COL__SYS_TABLES__N_COLS);
97 
98  ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
99  mach_write_to_4(ptr, table->n_def
100  | ((table->flags & DICT_TF_COMPACT) << 31));
101  dfield_set_data(dfield, ptr, 4);
102 
103  /* 5: TYPE (table flags) -----------------------------*/
104  dfield = dtuple_get_nth_field(
105  entry, DICT_COL__SYS_TABLES__TYPE);
106 
107  ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
108 
109  /* Validate the table flags and convert them to what is saved in
110  SYS_TABLES.TYPE. Table flag values 0 and 1 are both written to
111  SYS_TABLES.TYPE as 1. */
112  type = dict_tf_to_sys_tables_type(table->flags);
113  mach_write_to_4(ptr, type);
114 
115  dfield_set_data(dfield, ptr, 4);
116 
117  /* 6: MIX_ID (obsolete) ---------------------------*/
118  dfield = dtuple_get_nth_field(
119  entry, DICT_COL__SYS_TABLES__MIX_ID);
120 
121  ptr = static_cast<byte*>(mem_heap_zalloc(heap, 8));
122 
123  dfield_set_data(dfield, ptr, 8);
124 
125  /* 7: MIX_LEN (additional flags) --------------------------*/
126  dfield = dtuple_get_nth_field(
127  entry, DICT_COL__SYS_TABLES__MIX_LEN);
128 
129  ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
130  /* Be sure all non-used bits are zero. */
131  ut_a(!(table->flags2 & ~DICT_TF2_BIT_MASK));
132  mach_write_to_4(ptr, table->flags2);
133 
134  dfield_set_data(dfield, ptr, 4);
135 
136  /* 8: CLUSTER_NAME ---------------------*/
137  dfield = dtuple_get_nth_field(
138  entry, DICT_COL__SYS_TABLES__CLUSTER_ID);
139  dfield_set_null(dfield); /* not supported */
140 
141  /* 9: SPACE ----------------------------*/
142  dfield = dtuple_get_nth_field(
143  entry, DICT_COL__SYS_TABLES__SPACE);
144 
145  ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
146  mach_write_to_4(ptr, table->space);
147 
148  dfield_set_data(dfield, ptr, 4);
149  /*----------------------------------*/
150 
151  return(entry);
152 }
153 
154 /*****************************************************************/
158 static
159 dtuple_t*
160 dict_create_sys_columns_tuple(
161 /*==========================*/
162  const dict_table_t* table,
163  ulint i,
164  mem_heap_t* heap)
167 {
168  dict_table_t* sys_columns;
169  dtuple_t* entry;
170  const dict_col_t* column;
171  dfield_t* dfield;
172  byte* ptr;
173  const char* col_name;
174 
175  ut_ad(table);
176  ut_ad(heap);
177 
178  column = dict_table_get_nth_col(table, i);
179 
180  sys_columns = dict_sys->sys_columns;
181 
182  entry = dtuple_create(heap, 7 + DATA_N_SYS_COLS);
183 
184  dict_table_copy_types(entry, sys_columns);
185 
186  /* 0: TABLE_ID -----------------------*/
187  dfield = dtuple_get_nth_field(entry, DICT_COL__SYS_COLUMNS__TABLE_ID);
188 
189  ptr = static_cast<byte*>(mem_heap_alloc(heap, 8));
190  mach_write_to_8(ptr, table->id);
191 
192  dfield_set_data(dfield, ptr, 8);
193 
194  /* 1: POS ----------------------------*/
195  dfield = dtuple_get_nth_field(entry, DICT_COL__SYS_COLUMNS__POS);
196 
197  ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
198  mach_write_to_4(ptr, i);
199 
200  dfield_set_data(dfield, ptr, 4);
201 
202  /* 2: DB_TRX_ID added later */
203  /* 3: DB_ROLL_PTR added later */
204  /* 4: NAME ---------------------------*/
205  dfield = dtuple_get_nth_field(entry, DICT_COL__SYS_COLUMNS__NAME);
206 
207  col_name = dict_table_get_col_name(table, i);
208  dfield_set_data(dfield, col_name, ut_strlen(col_name));
209 
210  /* 5: MTYPE --------------------------*/
211  dfield = dtuple_get_nth_field(entry, DICT_COL__SYS_COLUMNS__MTYPE);
212 
213  ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
214  mach_write_to_4(ptr, column->mtype);
215 
216  dfield_set_data(dfield, ptr, 4);
217 
218  /* 6: PRTYPE -------------------------*/
219  dfield = dtuple_get_nth_field(entry, DICT_COL__SYS_COLUMNS__PRTYPE);
220 
221  ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
222  mach_write_to_4(ptr, column->prtype);
223 
224  dfield_set_data(dfield, ptr, 4);
225 
226  /* 7: LEN ----------------------------*/
227  dfield = dtuple_get_nth_field(entry, DICT_COL__SYS_COLUMNS__LEN);
228 
229  ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
230  mach_write_to_4(ptr, column->len);
231 
232  dfield_set_data(dfield, ptr, 4);
233 
234  /* 8: PREC ---------------------------*/
235  dfield = dtuple_get_nth_field(entry, DICT_COL__SYS_COLUMNS__PREC);
236 
237  ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
238  mach_write_to_4(ptr, 0/* unused */);
239 
240  dfield_set_data(dfield, ptr, 4);
241  /*---------------------------------*/
242 
243  return(entry);
244 }
245 
246 /***************************************************************/
249 static __attribute__((nonnull, warn_unused_result))
250 dberr_t
251 dict_build_table_def_step(
252 /*======================*/
253  que_thr_t* thr,
254  tab_node_t* node)
255 {
257  dtuple_t* row;
258  dberr_t error;
259  const char* path;
260  mtr_t mtr;
261  ulint space = 0;
262  bool use_tablespace;
263 
264  ut_ad(mutex_own(&(dict_sys->mutex)));
265 
266  table = node->table;
267  use_tablespace = DICT_TF2_FLAG_IS_SET(table, DICT_TF2_USE_TABLESPACE);
268 
269  dict_hdr_get_new_id(&table->id, NULL, NULL);
270 
271  thr_get_trx(thr)->table_id = table->id;
272 
273  if (use_tablespace) {
274  /* This table will not use the system tablespace.
275  Get a new space id. */
276  dict_hdr_get_new_id(NULL, NULL, &space);
277 
278  DBUG_EXECUTE_IF(
279  "ib_create_table_fail_out_of_space_ids",
280  space = ULINT_UNDEFINED;
281  );
282 
283  if (UNIV_UNLIKELY(space == ULINT_UNDEFINED)) {
284  return(DB_ERROR);
285  }
286 
287  /* We create a new single-table tablespace for the table.
288  We initially let it be 4 pages:
289  - page 0 is the fsp header and an extent descriptor page,
290  - page 1 is an ibuf bitmap page,
291  - page 2 is the first inode page,
292  - page 3 will contain the root of the clustered index of the
293  table we create here. */
294 
295  path = table->data_dir_path ? table->data_dir_path
296  : table->dir_path_of_temp_table;
297 
298  ut_ad(dict_table_get_format(table) <= UNIV_FORMAT_MAX);
299  ut_ad(!dict_table_zip_size(table)
300  || dict_table_get_format(table) >= UNIV_FORMAT_B);
301 
303  space, table->name, path,
304  dict_tf_to_fsp_flags(table->flags),
305  table->flags2,
307 
308  table->space = (unsigned int) space;
309 
310  if (error != DB_SUCCESS) {
311 
312  return(error);
313  }
314 
315  mtr_start(&mtr);
316 
318 
319  mtr_commit(&mtr);
320  } else {
321  /* Create in the system tablespace: disallow Barracuda
322  features by keeping only the first bit which says whether
323  the row format is redundant or compact */
324  table->flags &= DICT_TF_COMPACT;
325  }
326 
327  row = dict_create_sys_tables_tuple(table, node->heap);
328 
329  ins_node_set_new_row(node->tab_def, row);
330 
331  return(DB_SUCCESS);
332 }
333 
334 /***************************************************************/
336 static
337 void
338 dict_build_col_def_step(
339 /*====================*/
340  tab_node_t* node)
341 {
342  dtuple_t* row;
343 
344  row = dict_create_sys_columns_tuple(node->table, node->col_no,
345  node->heap);
346  ins_node_set_new_row(node->col_def, row);
347 }
348 
349 /*****************************************************************/
353 static
354 dtuple_t*
355 dict_create_sys_indexes_tuple(
356 /*==========================*/
357  const dict_index_t* index,
358  mem_heap_t* heap)
361 {
362  dict_table_t* sys_indexes;
364  dtuple_t* entry;
365  dfield_t* dfield;
366  byte* ptr;
367 
368  ut_ad(mutex_own(&(dict_sys->mutex)));
369  ut_ad(index);
370  ut_ad(heap);
371 
372  sys_indexes = dict_sys->sys_indexes;
373 
374  table = dict_table_get_low(index->table_name);
375 
376  entry = dtuple_create(heap, 7 + DATA_N_SYS_COLS);
377 
378  dict_table_copy_types(entry, sys_indexes);
379 
380  /* 0: TABLE_ID -----------------------*/
381  dfield = dtuple_get_nth_field(
382  entry, DICT_COL__SYS_INDEXES__TABLE_ID);
383 
384  ptr = static_cast<byte*>(mem_heap_alloc(heap, 8));
385  mach_write_to_8(ptr, table->id);
386 
387  dfield_set_data(dfield, ptr, 8);
388 
389  /* 1: ID ----------------------------*/
390  dfield = dtuple_get_nth_field(
391  entry, DICT_COL__SYS_INDEXES__ID);
392 
393  ptr = static_cast<byte*>(mem_heap_alloc(heap, 8));
394  mach_write_to_8(ptr, index->id);
395 
396  dfield_set_data(dfield, ptr, 8);
397 
398  /* 2: DB_TRX_ID added later */
399  /* 3: DB_ROLL_PTR added later */
400  /* 4: NAME --------------------------*/
401  dfield = dtuple_get_nth_field(
402  entry, DICT_COL__SYS_INDEXES__NAME);
403 
404  dfield_set_data(dfield, index->name, ut_strlen(index->name));
405 
406  /* 5: N_FIELDS ----------------------*/
407  dfield = dtuple_get_nth_field(
408  entry, DICT_COL__SYS_INDEXES__N_FIELDS);
409 
410  ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
411  mach_write_to_4(ptr, index->n_fields);
412 
413  dfield_set_data(dfield, ptr, 4);
414 
415  /* 6: TYPE --------------------------*/
416  dfield = dtuple_get_nth_field(
417  entry, DICT_COL__SYS_INDEXES__TYPE);
418 
419  ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
420  mach_write_to_4(ptr, index->type);
421 
422  dfield_set_data(dfield, ptr, 4);
423 
424  /* 7: SPACE --------------------------*/
425 
426  dfield = dtuple_get_nth_field(
427  entry, DICT_COL__SYS_INDEXES__SPACE);
428 
429  ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
430  mach_write_to_4(ptr, index->space);
431 
432  dfield_set_data(dfield, ptr, 4);
433 
434  /* 8: PAGE_NO --------------------------*/
435 
436  dfield = dtuple_get_nth_field(
437  entry, DICT_COL__SYS_INDEXES__PAGE_NO);
438 
439  ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
441 
442  dfield_set_data(dfield, ptr, 4);
443 
444  /*--------------------------------*/
445 
446  return(entry);
447 }
448 
449 /*****************************************************************/
453 static
454 dtuple_t*
455 dict_create_sys_fields_tuple(
456 /*=========================*/
457  const dict_index_t* index,
458  ulint fld_no,
459  mem_heap_t* heap)
462 {
463  dict_table_t* sys_fields;
464  dtuple_t* entry;
465  dict_field_t* field;
466  dfield_t* dfield;
467  byte* ptr;
468  ibool index_contains_column_prefix_field = FALSE;
469  ulint j;
470 
471  ut_ad(index);
472  ut_ad(heap);
473 
474  for (j = 0; j < index->n_fields; j++) {
475  if (dict_index_get_nth_field(index, j)->prefix_len > 0) {
476  index_contains_column_prefix_field = TRUE;
477  break;
478  }
479  }
480 
481  field = dict_index_get_nth_field(index, fld_no);
482 
483  sys_fields = dict_sys->sys_fields;
484 
485  entry = dtuple_create(heap, 3 + DATA_N_SYS_COLS);
486 
487  dict_table_copy_types(entry, sys_fields);
488 
489  /* 0: INDEX_ID -----------------------*/
490  dfield = dtuple_get_nth_field(entry, DICT_COL__SYS_FIELDS__INDEX_ID);
491 
492  ptr = static_cast<byte*>(mem_heap_alloc(heap, 8));
493  mach_write_to_8(ptr, index->id);
494 
495  dfield_set_data(dfield, ptr, 8);
496 
497  /* 1: POS; FIELD NUMBER & PREFIX LENGTH -----------------------*/
498 
499  dfield = dtuple_get_nth_field(entry, DICT_COL__SYS_FIELDS__POS);
500 
501  ptr = static_cast<byte*>(mem_heap_alloc(heap, 4));
502 
503  if (index_contains_column_prefix_field) {
504  /* If there are column prefix fields in the index, then
505  we store the number of the field to the 2 HIGH bytes
506  and the prefix length to the 2 low bytes, */
507 
508  mach_write_to_4(ptr, (fld_no << 16) + field->prefix_len);
509  } else {
510  /* Else we store the number of the field to the 2 LOW bytes.
511  This is to keep the storage format compatible with
512  InnoDB versions < 4.0.14. */
513 
514  mach_write_to_4(ptr, fld_no);
515  }
516 
517  dfield_set_data(dfield, ptr, 4);
518 
519  /* 2: DB_TRX_ID added later */
520  /* 3: DB_ROLL_PTR added later */
521  /* 4: COL_NAME -------------------------*/
522  dfield = dtuple_get_nth_field(entry, DICT_COL__SYS_FIELDS__COL_NAME);
523 
524  dfield_set_data(dfield, field->name,
525  ut_strlen(field->name));
526  /*---------------------------------*/
527 
528  return(entry);
529 }
530 
531 /*****************************************************************/
535 static
536 dtuple_t*
537 dict_create_search_tuple(
538 /*=====================*/
539  const dtuple_t* tuple,
541  mem_heap_t* heap)
543 {
544  dtuple_t* search_tuple;
545  const dfield_t* field1;
546  dfield_t* field2;
547 
548  ut_ad(tuple && heap);
549 
550  search_tuple = dtuple_create(heap, 2);
551 
552  field1 = dtuple_get_nth_field(tuple, 0);
553  field2 = dtuple_get_nth_field(search_tuple, 0);
554 
555  dfield_copy(field2, field1);
556 
557  field1 = dtuple_get_nth_field(tuple, 1);
558  field2 = dtuple_get_nth_field(search_tuple, 1);
559 
560  dfield_copy(field2, field1);
561 
562  ut_ad(dtuple_validate(search_tuple));
563 
564  return(search_tuple);
565 }
566 
567 /***************************************************************/
570 static __attribute__((nonnull, warn_unused_result))
571 dberr_t
572 dict_build_index_def_step(
573 /*======================*/
574  que_thr_t* thr,
575  ind_node_t* node)
576 {
579  dtuple_t* row;
580  trx_t* trx;
581 
582  ut_ad(mutex_own(&(dict_sys->mutex)));
583 
584  trx = thr_get_trx(thr);
585 
586  index = node->index;
587 
588  table = dict_table_get_low(index->table_name);
589 
590  if (table == NULL) {
591  return(DB_TABLE_NOT_FOUND);
592  }
593 
594  if (!trx->table_id) {
595  /* Record only the first table id. */
596  trx->table_id = table->id;
597  }
598 
599  node->table = table;
600 
601  ut_ad((UT_LIST_GET_LEN(table->indexes) > 0)
602  || dict_index_is_clust(index));
603 
604  dict_hdr_get_new_id(NULL, &index->id, NULL);
605 
606  /* Inherit the space id from the table; we store all indexes of a
607  table in the same tablespace */
608 
609  index->space = table->space;
610  node->page_no = FIL_NULL;
611  row = dict_create_sys_indexes_tuple(index, node->heap);
612  node->ind_row = row;
613 
614  ins_node_set_new_row(node->ind_def, row);
615 
616  /* Note that the index was created by this transaction. */
617  index->trx_id = trx->id;
618  ut_ad(table->def_trx_id <= trx->id);
619  table->def_trx_id = trx->id;
620 
621  return(DB_SUCCESS);
622 }
623 
624 /***************************************************************/
626 static
627 void
628 dict_build_field_def_step(
629 /*======================*/
630  ind_node_t* node)
631 {
633  dtuple_t* row;
634 
635  index = node->index;
636 
637  row = dict_create_sys_fields_tuple(index, node->field_no, node->heap);
638 
639  ins_node_set_new_row(node->field_def, row);
640 }
641 
642 /***************************************************************/
645 static __attribute__((nonnull, warn_unused_result))
646 dberr_t
647 dict_create_index_tree_step(
648 /*========================*/
649  ind_node_t* node)
650 {
652  dict_table_t* sys_indexes;
653  dtuple_t* search_tuple;
655  mtr_t mtr;
656 
657  ut_ad(mutex_own(&(dict_sys->mutex)));
658 
659  index = node->index;
660 
661  sys_indexes = dict_sys->sys_indexes;
662 
663  if (index->type == DICT_FTS) {
664  /* FTS index does not need an index tree */
665  return(DB_SUCCESS);
666  }
667 
668  /* Run a mini-transaction in which the index tree is allocated for
669  the index and its root address is written to the index entry in
670  sys_indexes */
671 
672  mtr_start(&mtr);
673 
674  search_tuple = dict_create_search_tuple(node->ind_row, node->heap);
675 
676  btr_pcur_open(UT_LIST_GET_FIRST(sys_indexes->indexes),
677  search_tuple, PAGE_CUR_L, BTR_MODIFY_LEAF,
678  &pcur, &mtr);
679 
680  btr_pcur_move_to_next_user_rec(&pcur, &mtr);
681 
682 
683  dberr_t err = DB_SUCCESS;
684  ulint zip_size = dict_table_zip_size(index->table);
685 
686  if (node->index->table->ibd_file_missing
687  || dict_table_is_discarded(node->index->table)) {
688 
689  node->page_no = FIL_NULL;
690  } else {
691  node->page_no = btr_create(
692  index->type, index->space, zip_size,
693  index->id, index, &mtr);
694 
695  if (node->page_no == FIL_NULL) {
696  err = DB_OUT_OF_FILE_SPACE;
697  }
698 
699  DBUG_EXECUTE_IF("ib_import_create_index_failure_1",
700  node->page_no = FIL_NULL;
701  err = DB_OUT_OF_FILE_SPACE; );
702  }
703 
705  btr_pcur_get_rec(&pcur), DICT_FLD__SYS_INDEXES__PAGE_NO,
706  node->page_no, &mtr);
707 
708  btr_pcur_close(&pcur);
709 
710  mtr_commit(&mtr);
711 
712  return(err);
713 }
714 
715 /*******************************************************************/
717 UNIV_INTERN
718 void
720 /*=================*/
721  rec_t* rec,
723  mtr_t* mtr)
724 {
725  ulint root_page_no;
726  ulint space;
727  ulint zip_size;
728  const byte* ptr;
729  ulint len;
730 
731  ut_ad(mutex_own(&(dict_sys->mutex)));
733  ptr = rec_get_nth_field_old(
734  rec, DICT_FLD__SYS_INDEXES__PAGE_NO, &len);
735 
736  ut_ad(len == 4);
737 
738  root_page_no = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
739 
740  if (root_page_no == FIL_NULL) {
741  /* The tree has already been freed */
742 
743  return;
744  }
745 
746  ptr = rec_get_nth_field_old(
747  rec, DICT_FLD__SYS_INDEXES__SPACE, &len);
748 
749  ut_ad(len == 4);
750 
751  space = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
752  zip_size = fil_space_get_zip_size(space);
753 
754  if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
755  /* It is a single table tablespace and the .ibd file is
756  missing: do nothing */
757 
758  return;
759  }
760 
761  /* We free all the pages but the root page first; this operation
762  may span several mini-transactions */
763 
764  btr_free_but_not_root(space, zip_size, root_page_no);
765 
766  /* Then we free the root page in the same mini-transaction where
767  we write FIL_NULL to the appropriate field in the SYS_INDEXES
768  record: this mini-transaction marks the B-tree totally freed */
769 
770  /* printf("Dropping index tree in space %lu root page %lu\n", space,
771  root_page_no); */
772  btr_free_root(space, zip_size, root_page_no, mtr);
773 
774  page_rec_write_field(rec, DICT_FLD__SYS_INDEXES__PAGE_NO,
775  FIL_NULL, mtr);
776 }
777 
778 /*******************************************************************/
781 UNIV_INTERN
782 ulint
784 /*=====================*/
785  dict_table_t* table,
786  ulint space,
789  btr_pcur_t* pcur,
793  mtr_t* mtr)
796 {
797  ulint root_page_no;
798  ibool drop = !space;
799  ulint zip_size;
800  ulint type;
801  index_id_t index_id;
802  rec_t* rec;
803  const byte* ptr;
804  ulint len;
806 
807  ut_ad(mutex_own(&(dict_sys->mutex)));
809  rec = btr_pcur_get_rec(pcur);
810  ptr = rec_get_nth_field_old(
811  rec, DICT_FLD__SYS_INDEXES__PAGE_NO, &len);
812 
813  ut_ad(len == 4);
814 
815  root_page_no = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
816 
817  if (drop && root_page_no == FIL_NULL) {
818  /* The tree has been freed. */
819 
820  ut_print_timestamp(stderr);
821  fprintf(stderr, " InnoDB: Trying to TRUNCATE"
822  " a missing index of table %s!\n", table->name);
823  drop = FALSE;
824  }
825 
826  ptr = rec_get_nth_field_old(
827  rec, DICT_FLD__SYS_INDEXES__SPACE, &len);
828 
829  ut_ad(len == 4);
830 
831  if (drop) {
832  space = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
833  }
834 
835  zip_size = fil_space_get_zip_size(space);
836 
837  if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
838  /* It is a single table tablespace and the .ibd file is
839  missing: do nothing */
840 
841  ut_print_timestamp(stderr);
842  fprintf(stderr, " InnoDB: Trying to TRUNCATE"
843  " a missing .ibd file of table %s!\n", table->name);
844  return(FIL_NULL);
845  }
846 
847  ptr = rec_get_nth_field_old(
848  rec, DICT_FLD__SYS_INDEXES__TYPE, &len);
849  ut_ad(len == 4);
850  type = mach_read_from_4(ptr);
851 
852  ptr = rec_get_nth_field_old(rec, DICT_FLD__SYS_INDEXES__ID, &len);
853  ut_ad(len == 8);
854  index_id = mach_read_from_8(ptr);
855 
856  if (!drop) {
857 
858  goto create;
859  }
860 
861  /* We free all the pages but the root page first; this operation
862  may span several mini-transactions */
863 
864  btr_free_but_not_root(space, zip_size, root_page_no);
865 
866  /* Then we free the root page in the same mini-transaction where
867  we create the b-tree and write its new root page number to the
868  appropriate field in the SYS_INDEXES record: this mini-transaction
869  marks the B-tree totally truncated */
870 
871  btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, NULL, mtr);
872 
873  btr_free_root(space, zip_size, root_page_no, mtr);
874 create:
875  /* We will temporarily write FIL_NULL to the PAGE_NO field
876  in SYS_INDEXES, so that the database will not get into an
877  inconsistent state in case it crashes between the mtr_commit()
878  below and the following mtr_commit() call. */
879  page_rec_write_field(rec, DICT_FLD__SYS_INDEXES__PAGE_NO,
880  FIL_NULL, mtr);
881 
882  /* We will need to commit the mini-transaction in order to avoid
883  deadlocks in the btr_create() call, because otherwise we would
884  be freeing and allocating pages in the same mini-transaction. */
885  btr_pcur_store_position(pcur, mtr);
886  mtr_commit(mtr);
887 
888  mtr_start(mtr);
889  btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr);
890 
891  /* Find the index corresponding to this SYS_INDEXES record. */
892  for (index = UT_LIST_GET_FIRST(table->indexes);
893  index;
894  index = UT_LIST_GET_NEXT(indexes, index)) {
895  if (index->id == index_id) {
896  if (index->type & DICT_FTS) {
897  return(FIL_NULL);
898  } else {
899  root_page_no = btr_create(type, space, zip_size,
900  index_id, index, mtr);
901  index->page = (unsigned int) root_page_no;
902  return(root_page_no);
903  }
904  }
905  }
906 
907  ut_print_timestamp(stderr);
908  fprintf(stderr,
909  " InnoDB: Index %llu of table %s is missing\n"
910  "InnoDB: from the data dictionary during TRUNCATE!\n",
911  (ullint) index_id,
912  table->name);
913 
914  return(FIL_NULL);
915 }
916 
917 /*********************************************************************/
920 UNIV_INTERN
921 tab_node_t*
923 /*====================*/
924  dict_table_t* table,
926  mem_heap_t* heap,
927  bool commit)
929 {
930  tab_node_t* node;
931 
932  node = static_cast<tab_node_t*>(
933  mem_heap_alloc(heap, sizeof(tab_node_t)));
934 
935  node->common.type = QUE_NODE_CREATE_TABLE;
936 
937  node->table = table;
938 
939  node->state = TABLE_BUILD_TABLE_DEF;
940  node->heap = mem_heap_create(256);
941 
942  node->tab_def = ins_node_create(INS_DIRECT, dict_sys->sys_tables,
943  heap);
944  node->tab_def->common.parent = node;
945 
946  node->col_def = ins_node_create(INS_DIRECT, dict_sys->sys_columns,
947  heap);
948  node->col_def->common.parent = node;
949 
950  if (commit) {
951  node->commit_node = trx_commit_node_create(heap);
952  node->commit_node->common.parent = node;
953  } else {
954  node->commit_node = 0;
955  }
956 
957  return(node);
958 }
959 
960 /*********************************************************************/
963 UNIV_INTERN
964 ind_node_t*
966 /*====================*/
967  dict_index_t* index,
969  mem_heap_t* heap,
970  bool commit)
972 {
973  ind_node_t* node;
974 
975  node = static_cast<ind_node_t*>(
976  mem_heap_alloc(heap, sizeof(ind_node_t)));
977 
978  node->common.type = QUE_NODE_CREATE_INDEX;
979 
980  node->index = index;
981 
982  node->state = INDEX_BUILD_INDEX_DEF;
983  node->page_no = FIL_NULL;
984  node->heap = mem_heap_create(256);
985 
986  node->ind_def = ins_node_create(INS_DIRECT,
987  dict_sys->sys_indexes, heap);
988  node->ind_def->common.parent = node;
989 
990  node->field_def = ins_node_create(INS_DIRECT,
991  dict_sys->sys_fields, heap);
992  node->field_def->common.parent = node;
993 
994  if (commit) {
995  node->commit_node = trx_commit_node_create(heap);
996  node->commit_node->common.parent = node;
997  } else {
998  node->commit_node = 0;
999  }
1000 
1001  return(node);
1002 }
1003 
1004 /***********************************************************/
1007 UNIV_INTERN
1008 que_thr_t*
1010 /*===================*/
1011  que_thr_t* thr)
1012 {
1013  tab_node_t* node;
1014  dberr_t err = DB_ERROR;
1015  trx_t* trx;
1016 
1017  ut_ad(thr);
1018  ut_ad(mutex_own(&(dict_sys->mutex)));
1019 
1020  trx = thr_get_trx(thr);
1021 
1022  node = static_cast<tab_node_t*>(thr->run_node);
1023 
1024  ut_ad(que_node_get_type(node) == QUE_NODE_CREATE_TABLE);
1025 
1026  if (thr->prev_node == que_node_get_parent(node)) {
1027  node->state = TABLE_BUILD_TABLE_DEF;
1028  }
1029 
1030  if (node->state == TABLE_BUILD_TABLE_DEF) {
1031 
1032  /* DO THE CHECKS OF THE CONSISTENCY CONSTRAINTS HERE */
1033 
1034  err = dict_build_table_def_step(thr, node);
1035 
1036  if (err != DB_SUCCESS) {
1037 
1038  goto function_exit;
1039  }
1040 
1041  node->state = TABLE_BUILD_COL_DEF;
1042  node->col_no = 0;
1043 
1044  thr->run_node = node->tab_def;
1045 
1046  return(thr);
1047  }
1048 
1049  if (node->state == TABLE_BUILD_COL_DEF) {
1050 
1051  if (node->col_no < (node->table)->n_def) {
1052 
1053  dict_build_col_def_step(node);
1054 
1055  node->col_no++;
1056 
1057  thr->run_node = node->col_def;
1058 
1059  return(thr);
1060  } else {
1061  node->state = TABLE_COMMIT_WORK;
1062  }
1063  }
1064 
1065  if (node->state == TABLE_COMMIT_WORK) {
1066 
1067  /* Table was correctly defined: do NOT commit the transaction
1068  (CREATE TABLE does NOT do an implicit commit of the current
1069  transaction) */
1070 
1071  node->state = TABLE_ADD_TO_CACHE;
1072 
1073  /* thr->run_node = node->commit_node;
1074 
1075  return(thr); */
1076  }
1077 
1078  if (node->state == TABLE_ADD_TO_CACHE) {
1079 
1080  dict_table_add_to_cache(node->table, TRUE, node->heap);
1081 
1082  err = DB_SUCCESS;
1083  }
1084 
1085 function_exit:
1086  trx->error_state = err;
1087 
1088  if (err == DB_SUCCESS) {
1089  /* Ok: do nothing */
1090 
1091  } else if (err == DB_LOCK_WAIT) {
1092 
1093  return(NULL);
1094  } else {
1095  /* SQL error detected */
1096 
1097  return(NULL);
1098  }
1099 
1100  thr->run_node = que_node_get_parent(node);
1101 
1102  return(thr);
1103 }
1104 
1105 /***********************************************************/
1109 UNIV_INTERN
1110 que_thr_t*
1112 /*===================*/
1113  que_thr_t* thr)
1114 {
1115  ind_node_t* node;
1116  dberr_t err = DB_ERROR;
1117  trx_t* trx;
1118 
1119  ut_ad(thr);
1120  ut_ad(mutex_own(&(dict_sys->mutex)));
1121 
1122  trx = thr_get_trx(thr);
1123 
1124  node = static_cast<ind_node_t*>(thr->run_node);
1125 
1126  ut_ad(que_node_get_type(node) == QUE_NODE_CREATE_INDEX);
1127 
1128  if (thr->prev_node == que_node_get_parent(node)) {
1129  node->state = INDEX_BUILD_INDEX_DEF;
1130  }
1131 
1132  if (node->state == INDEX_BUILD_INDEX_DEF) {
1133  /* DO THE CHECKS OF THE CONSISTENCY CONSTRAINTS HERE */
1134  err = dict_build_index_def_step(thr, node);
1135 
1136  if (err != DB_SUCCESS) {
1137 
1138  goto function_exit;
1139  }
1140 
1141  node->state = INDEX_BUILD_FIELD_DEF;
1142  node->field_no = 0;
1143 
1144  thr->run_node = node->ind_def;
1145 
1146  return(thr);
1147  }
1148 
1149  if (node->state == INDEX_BUILD_FIELD_DEF) {
1150 
1151  if (node->field_no < (node->index)->n_fields) {
1152 
1153  dict_build_field_def_step(node);
1154 
1155  node->field_no++;
1156 
1157  thr->run_node = node->field_def;
1158 
1159  return(thr);
1160  } else {
1161  node->state = INDEX_ADD_TO_CACHE;
1162  }
1163  }
1164 
1165  if (node->state == INDEX_ADD_TO_CACHE) {
1166 
1167  index_id_t index_id = node->index->id;
1168 
1170  node->table, node->index, FIL_NULL,
1171  trx_is_strict(trx)
1172  || dict_table_get_format(node->table)
1173  >= UNIV_FORMAT_B);
1174 
1175  node->index = dict_index_get_if_in_cache_low(index_id);
1176  ut_a(!node->index == (err != DB_SUCCESS));
1177 
1178  if (err != DB_SUCCESS) {
1179 
1180  goto function_exit;
1181  }
1182 
1183  node->state = INDEX_CREATE_INDEX_TREE;
1184  }
1185 
1186  if (node->state == INDEX_CREATE_INDEX_TREE) {
1187 
1188  err = dict_create_index_tree_step(node);
1189 
1190  DBUG_EXECUTE_IF("ib_dict_create_index_tree_fail",
1191  err = DB_OUT_OF_MEMORY;);
1192 
1193  if (err != DB_SUCCESS) {
1194  /* If this is a FTS index, we will need to remove
1195  it from fts->cache->indexes list as well */
1196  if ((node->index->type & DICT_FTS)
1197  && node->table->fts) {
1198  fts_index_cache_t* index_cache;
1199 
1200  rw_lock_x_lock(
1201  &node->table->fts->cache->init_lock);
1202 
1203  index_cache = (fts_index_cache_t*)
1205  node->table->fts->cache,
1206  node->index);
1207 
1208  if (index_cache->words) {
1209  rbt_free(index_cache->words);
1210  index_cache->words = 0;
1211  }
1212 
1214  node->table->fts->cache->indexes,
1215  *reinterpret_cast<void**>(index_cache));
1216 
1217  rw_lock_x_unlock(
1218  &node->table->fts->cache->init_lock);
1219  }
1220 
1222  node->index = NULL;
1223 
1224  goto function_exit;
1225  }
1226 
1227  node->index->page = node->page_no;
1228  /* These should have been set in
1229  dict_build_index_def_step() and
1230  dict_index_add_to_cache(). */
1231  ut_ad(node->index->trx_id == trx->id);
1232  ut_ad(node->index->table->def_trx_id == trx->id);
1233  node->state = INDEX_COMMIT_WORK;
1234  }
1235 
1236  if (node->state == INDEX_COMMIT_WORK) {
1237 
1238  /* Index was correctly defined: do NOT commit the transaction
1239  (CREATE INDEX does NOT currently do an implicit commit of
1240  the current transaction) */
1241 
1242  node->state = INDEX_CREATE_INDEX_TREE;
1243 
1244  /* thr->run_node = node->commit_node;
1245 
1246  return(thr); */
1247  }
1248 
1249 function_exit:
1250  trx->error_state = err;
1251 
1252  if (err == DB_SUCCESS) {
1253  /* Ok: do nothing */
1254 
1255  } else if (err == DB_LOCK_WAIT) {
1256 
1257  return(NULL);
1258  } else {
1259  /* SQL error detected */
1260 
1261  return(NULL);
1262  }
1263 
1264  thr->run_node = que_node_get_parent(node);
1265 
1266  return(thr);
1267 }
1268 
1269 /****************************************************************/
1277 static
1278 dberr_t
1279 dict_check_if_system_table_exists(
1280 /*==============================*/
1281  const char* tablename,
1282  ulint num_fields,
1283  ulint num_indexes)
1284 {
1285  dict_table_t* sys_table;
1286  dberr_t error = DB_SUCCESS;
1287 
1289 
1290  mutex_enter(&dict_sys->mutex);
1291 
1292  sys_table = dict_table_get_low(tablename);
1293 
1294  if (sys_table == NULL) {
1295  error = DB_TABLE_NOT_FOUND;
1296 
1297  } else if (UT_LIST_GET_LEN(sys_table->indexes) != num_indexes
1298  || sys_table->n_cols != num_fields) {
1299  error = DB_CORRUPTION;
1300 
1301  } else {
1302  /* This table has already been created, and it is OK.
1303  Ensure that it can't be evicted from the table LRU cache. */
1304 
1306  }
1307 
1308  mutex_exit(&dict_sys->mutex);
1309 
1310  return(error);
1311 }
1312 
1313 /****************************************************************/
1318 UNIV_INTERN
1319 dberr_t
1321 /*================================================*/
1322 {
1323  trx_t* trx;
1324  my_bool srv_file_per_table_backup;
1325  dberr_t err;
1326  dberr_t sys_foreign_err;
1327  dberr_t sys_foreign_cols_err;
1328 
1330 
1331  /* Note: The master thread has not been started at this point. */
1332 
1333 
1334  sys_foreign_err = dict_check_if_system_table_exists(
1335  "SYS_FOREIGN", DICT_NUM_FIELDS__SYS_FOREIGN + 1, 3);
1336  sys_foreign_cols_err = dict_check_if_system_table_exists(
1337  "SYS_FOREIGN_COLS", DICT_NUM_FIELDS__SYS_FOREIGN_COLS + 1, 1);
1338 
1339  if (sys_foreign_err == DB_SUCCESS
1340  && sys_foreign_cols_err == DB_SUCCESS) {
1341  return(DB_SUCCESS);
1342  }
1343 
1344  trx = trx_allocate_for_mysql();
1345 
1347 
1348  trx->op_info = "creating foreign key sys tables";
1349 
1350  row_mysql_lock_data_dictionary(trx);
1351 
1352  /* Check which incomplete table definition to drop. */
1353 
1354  if (sys_foreign_err == DB_CORRUPTION) {
1355  ib_logf(IB_LOG_LEVEL_WARN,
1356  "Dropping incompletely created "
1357  "SYS_FOREIGN table.");
1358  row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE);
1359  }
1360 
1361  if (sys_foreign_cols_err == DB_CORRUPTION) {
1362  ib_logf(IB_LOG_LEVEL_WARN,
1363  "Dropping incompletely created "
1364  "SYS_FOREIGN_COLS table.");
1365 
1366  row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE);
1367  }
1368 
1369  ib_logf(IB_LOG_LEVEL_WARN,
1370  "Creating foreign key constraint system tables.");
1371 
1372  /* NOTE: in dict_load_foreigns we use the fact that
1373  there are 2 secondary indexes on SYS_FOREIGN, and they
1374  are defined just like below */
1375 
1376  /* NOTE: when designing InnoDB's foreign key support in 2001, we made
1377  an error and made the table names and the foreign key id of type
1378  'CHAR' (internally, really a VARCHAR). We should have made the type
1379  VARBINARY, like in other InnoDB system tables, to get a clean
1380  design. */
1381 
1382  srv_file_per_table_backup = srv_file_per_table;
1383 
1384  /* We always want SYSTEM tables to be created inside the system
1385  tablespace. */
1386 
1387  srv_file_per_table = 0;
1388 
1389  err = que_eval_sql(
1390  NULL,
1391  "PROCEDURE CREATE_FOREIGN_SYS_TABLES_PROC () IS\n"
1392  "BEGIN\n"
1393  "CREATE TABLE\n"
1394  "SYS_FOREIGN(ID CHAR, FOR_NAME CHAR,"
1395  " REF_NAME CHAR, N_COLS INT);\n"
1396  "CREATE UNIQUE CLUSTERED INDEX ID_IND"
1397  " ON SYS_FOREIGN (ID);\n"
1398  "CREATE INDEX FOR_IND"
1399  " ON SYS_FOREIGN (FOR_NAME);\n"
1400  "CREATE INDEX REF_IND"
1401  " ON SYS_FOREIGN (REF_NAME);\n"
1402  "CREATE TABLE\n"
1403  "SYS_FOREIGN_COLS(ID CHAR, POS INT,"
1404  " FOR_COL_NAME CHAR, REF_COL_NAME CHAR);\n"
1405  "CREATE UNIQUE CLUSTERED INDEX ID_IND"
1406  " ON SYS_FOREIGN_COLS (ID, POS);\n"
1407  "END;\n",
1408  FALSE, trx);
1409 
1410  if (err != DB_SUCCESS) {
1411  ib_logf(IB_LOG_LEVEL_ERROR,
1412  "Creation of SYS_FOREIGN and SYS_FOREIGN_COLS "
1413  "has failed with error %lu. Tablespace is full. "
1414  "Dropping incompletely created tables.",
1415  (ulong) err);
1416 
1417  ut_ad(err == DB_OUT_OF_FILE_SPACE
1418  || err == DB_TOO_MANY_CONCURRENT_TRXS);
1419 
1420  row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE);
1421  row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE);
1422 
1423  if (err == DB_OUT_OF_FILE_SPACE) {
1425  }
1426  }
1427 
1428  trx_commit_for_mysql(trx);
1429 
1431 
1432  trx_free_for_mysql(trx);
1433 
1434  srv_file_per_table = srv_file_per_table_backup;
1435 
1436  if (err == DB_SUCCESS) {
1437  ib_logf(IB_LOG_LEVEL_INFO,
1438  "Foreign key constraint system tables created");
1439  }
1440 
1441  /* Note: The master thread has not been started at this point. */
1442  /* Confirm and move to the non-LRU part of the table LRU list. */
1443  sys_foreign_err = dict_check_if_system_table_exists(
1444  "SYS_FOREIGN", DICT_NUM_FIELDS__SYS_FOREIGN + 1, 3);
1445  ut_a(sys_foreign_err == DB_SUCCESS);
1446 
1447  sys_foreign_cols_err = dict_check_if_system_table_exists(
1448  "SYS_FOREIGN_COLS", DICT_NUM_FIELDS__SYS_FOREIGN_COLS + 1, 1);
1449  ut_a(sys_foreign_cols_err == DB_SUCCESS);
1450 
1451  return(err);
1452 }
1453 
1454 /****************************************************************/
1457 static __attribute__((nonnull, warn_unused_result))
1458 dberr_t
1459 dict_foreign_eval_sql(
1460 /*==================*/
1461  pars_info_t* info,
1462  const char* sql,
1463  const char* name,
1464  const char* id,
1465  trx_t* trx)
1466 {
1467  dberr_t error;
1468  FILE* ef = dict_foreign_err_file;
1469 
1470  error = que_eval_sql(info, sql, FALSE, trx);
1471 
1472  if (error == DB_DUPLICATE_KEY) {
1473  mutex_enter(&dict_foreign_err_mutex);
1474  rewind(ef);
1475  ut_print_timestamp(ef);
1476  fputs(" Error in foreign key constraint creation for table ",
1477  ef);
1478  ut_print_name(ef, trx, TRUE, name);
1479  fputs(".\nA foreign key constraint of name ", ef);
1480  ut_print_name(ef, trx, TRUE, id);
1481  fputs("\nalready exists."
1482  " (Note that internally InnoDB adds 'databasename'\n"
1483  "in front of the user-defined constraint name.)\n"
1484  "Note that InnoDB's FOREIGN KEY system tables store\n"
1485  "constraint names as case-insensitive, with the\n"
1486  "MySQL standard latin1_swedish_ci collation. If you\n"
1487  "create tables or databases whose names differ only in\n"
1488  "the character case, then collisions in constraint\n"
1489  "names can occur. Workaround: name your constraints\n"
1490  "explicitly with unique names.\n",
1491  ef);
1492 
1493  mutex_exit(&dict_foreign_err_mutex);
1494 
1495  return(error);
1496  }
1497 
1498  if (error != DB_SUCCESS) {
1499  fprintf(stderr,
1500  "InnoDB: Foreign key constraint creation failed:\n"
1501  "InnoDB: internal error number %lu\n", (ulong) error);
1502 
1503  mutex_enter(&dict_foreign_err_mutex);
1504  ut_print_timestamp(ef);
1505  fputs(" Internal error in foreign key constraint creation"
1506  " for table ", ef);
1507  ut_print_name(ef, trx, TRUE, name);
1508  fputs(".\n"
1509  "See the MySQL .err log in the datadir"
1510  " for more information.\n", ef);
1511  mutex_exit(&dict_foreign_err_mutex);
1512 
1513  return(error);
1514  }
1515 
1516  return(DB_SUCCESS);
1517 }
1518 
1519 /********************************************************************/
1523 static __attribute__((nonnull, warn_unused_result))
1524 dberr_t
1525 dict_create_add_foreign_field_to_dictionary(
1526 /*========================================*/
1527  ulint field_nr,
1528  const char* table_name,
1529  const dict_foreign_t* foreign,
1530  trx_t* trx)
1531 {
1532  pars_info_t* info = pars_info_create();
1533 
1534  pars_info_add_str_literal(info, "id", foreign->id);
1535 
1536  pars_info_add_int4_literal(info, "pos", field_nr);
1537 
1538  pars_info_add_str_literal(info, "for_col_name",
1539  foreign->foreign_col_names[field_nr]);
1540 
1541  pars_info_add_str_literal(info, "ref_col_name",
1542  foreign->referenced_col_names[field_nr]);
1543 
1544  return(dict_foreign_eval_sql(
1545  info,
1546  "PROCEDURE P () IS\n"
1547  "BEGIN\n"
1548  "INSERT INTO SYS_FOREIGN_COLS VALUES"
1549  "(:id, :pos, :for_col_name, :ref_col_name);\n"
1550  "END;\n",
1551  table_name, foreign->id, trx));
1552 }
1553 
1554 /********************************************************************/
1557 UNIV_INTERN
1558 dberr_t
1560 /*==================================*/
1561  const char* name,
1562  const dict_foreign_t* foreign,
1563  trx_t* trx)
1564 {
1565  dberr_t error;
1566  pars_info_t* info = pars_info_create();
1567 
1568  pars_info_add_str_literal(info, "id", foreign->id);
1569 
1570  pars_info_add_str_literal(info, "for_name", name);
1571 
1572  pars_info_add_str_literal(info, "ref_name",
1573  foreign->referenced_table_name);
1574 
1575  pars_info_add_int4_literal(info, "n_cols",
1576  foreign->n_fields + (foreign->type << 24));
1577 
1578  error = dict_foreign_eval_sql(info,
1579  "PROCEDURE P () IS\n"
1580  "BEGIN\n"
1581  "INSERT INTO SYS_FOREIGN VALUES"
1582  "(:id, :for_name, :ref_name, :n_cols);\n"
1583  "END;\n"
1584  , name, foreign->id, trx);
1585 
1586  if (error != DB_SUCCESS) {
1587 
1588  return(error);
1589  }
1590 
1591  for (ulint i = 0; i < foreign->n_fields; i++) {
1592  error = dict_create_add_foreign_field_to_dictionary(
1593  i, name, foreign, trx);
1594 
1595  if (error != DB_SUCCESS) {
1596 
1597  return(error);
1598  }
1599  }
1600 
1601  return(error);
1602 }
1603 
1604 /********************************************************************/
1607 UNIV_INTERN
1608 dberr_t
1610 /*===================================*/
1611  ulint start_id,
1619  dict_table_t* table,
1620  trx_t* trx)
1621 {
1622  dict_foreign_t* foreign;
1623  ulint number = start_id + 1;
1624  dberr_t error;
1625 
1626  ut_ad(mutex_own(&(dict_sys->mutex)));
1627 
1628  if (NULL == dict_table_get_low("SYS_FOREIGN")) {
1629  fprintf(stderr,
1630  "InnoDB: table SYS_FOREIGN not found"
1631  " in internal data dictionary\n");
1632 
1633  return(DB_ERROR);
1634  }
1635 
1636  for (foreign = UT_LIST_GET_FIRST(table->foreign_list);
1637  foreign;
1638  foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
1639 
1640  error = dict_create_add_foreign_id(&number, table->name,
1641  foreign);
1642 
1643  if (error != DB_SUCCESS) {
1644 
1645  return(error);
1646  }
1647 
1649  foreign, trx);
1650 
1651  if (error != DB_SUCCESS) {
1652 
1653  return(error);
1654  }
1655  }
1656 
1657  trx->op_info = "committing foreign key definitions";
1658 
1659  trx_commit(trx);
1660 
1661  trx->op_info = "";
1662 
1663  return(DB_SUCCESS);
1664 }
1665 
1666 /****************************************************************/
1671 UNIV_INTERN
1672 dberr_t
1674 /*=====================================*/
1675 {
1676  trx_t* trx;
1677  my_bool srv_file_per_table_backup;
1678  dberr_t err;
1679  dberr_t sys_tablespaces_err;
1680  dberr_t sys_datafiles_err;
1681 
1683 
1684  /* Note: The master thread has not been started at this point. */
1685 
1686  sys_tablespaces_err = dict_check_if_system_table_exists(
1687  "SYS_TABLESPACES", DICT_NUM_FIELDS__SYS_TABLESPACES + 1, 1);
1688  sys_datafiles_err = dict_check_if_system_table_exists(
1689  "SYS_DATAFILES", DICT_NUM_FIELDS__SYS_DATAFILES + 1, 1);
1690 
1691  if (sys_tablespaces_err == DB_SUCCESS
1692  && sys_datafiles_err == DB_SUCCESS) {
1693  return(DB_SUCCESS);
1694  }
1695 
1696  trx = trx_allocate_for_mysql();
1697 
1699 
1700  trx->op_info = "creating tablepace and datafile sys tables";
1701 
1702  row_mysql_lock_data_dictionary(trx);
1703 
1704  /* Check which incomplete table definition to drop. */
1705 
1706  if (sys_tablespaces_err == DB_CORRUPTION) {
1707  ib_logf(IB_LOG_LEVEL_WARN,
1708  "Dropping incompletely created "
1709  "SYS_TABLESPACES table.");
1710  row_drop_table_for_mysql("SYS_TABLESPACES", trx, TRUE);
1711  }
1712 
1713  if (sys_datafiles_err == DB_CORRUPTION) {
1714  ib_logf(IB_LOG_LEVEL_WARN,
1715  "Dropping incompletely created "
1716  "SYS_DATAFILES table.");
1717 
1718  row_drop_table_for_mysql("SYS_DATAFILES", trx, TRUE);
1719  }
1720 
1721  ib_logf(IB_LOG_LEVEL_INFO,
1722  "Creating tablespace and datafile system tables.");
1723 
1724  /* We always want SYSTEM tables to be created inside the system
1725  tablespace. */
1726  srv_file_per_table_backup = srv_file_per_table;
1727  srv_file_per_table = 0;
1728 
1729  err = que_eval_sql(
1730  NULL,
1731  "PROCEDURE CREATE_SYS_TABLESPACE_PROC () IS\n"
1732  "BEGIN\n"
1733  "CREATE TABLE SYS_TABLESPACES(\n"
1734  " SPACE INT, NAME CHAR, FLAGS INT);\n"
1735  "CREATE UNIQUE CLUSTERED INDEX SYS_TABLESPACES_SPACE"
1736  " ON SYS_TABLESPACES (SPACE);\n"
1737  "CREATE TABLE SYS_DATAFILES(\n"
1738  " SPACE INT, PATH CHAR);\n"
1739  "CREATE UNIQUE CLUSTERED INDEX SYS_DATAFILES_SPACE"
1740  " ON SYS_DATAFILES (SPACE);\n"
1741  "END;\n",
1742  FALSE, trx);
1743 
1744  if (err != DB_SUCCESS) {
1745  ib_logf(IB_LOG_LEVEL_ERROR,
1746  "Creation of SYS_TABLESPACES and SYS_DATAFILES "
1747  "has failed with error %lu. Tablespace is full. "
1748  "Dropping incompletely created tables.",
1749  (ulong) err);
1750 
1751  ut_a(err == DB_OUT_OF_FILE_SPACE
1752  || err == DB_TOO_MANY_CONCURRENT_TRXS);
1753 
1754  row_drop_table_for_mysql("SYS_TABLESPACES", trx, TRUE);
1755  row_drop_table_for_mysql("SYS_DATAFILES", trx, TRUE);
1756 
1757  if (err == DB_OUT_OF_FILE_SPACE) {
1759  }
1760  }
1761 
1762  trx_commit_for_mysql(trx);
1763 
1765 
1766  trx_free_for_mysql(trx);
1767 
1768  srv_file_per_table = srv_file_per_table_backup;
1769 
1770  if (err == DB_SUCCESS) {
1771  ib_logf(IB_LOG_LEVEL_INFO,
1772  "Tablespace and datafile system tables created.");
1773  }
1774 
1775  /* Note: The master thread has not been started at this point. */
1776  /* Confirm and move to the non-LRU part of the table LRU list. */
1777 
1778  sys_tablespaces_err = dict_check_if_system_table_exists(
1779  "SYS_TABLESPACES", DICT_NUM_FIELDS__SYS_TABLESPACES + 1, 1);
1780  ut_a(sys_tablespaces_err == DB_SUCCESS);
1781 
1782  sys_datafiles_err = dict_check_if_system_table_exists(
1783  "SYS_DATAFILES", DICT_NUM_FIELDS__SYS_DATAFILES + 1, 1);
1784  ut_a(sys_datafiles_err == DB_SUCCESS);
1785 
1786  return(err);
1787 }
1788 
1789 /********************************************************************/
1793 UNIV_INTERN
1794 dberr_t
1796 /*=====================================*/
1797  ulint space,
1798  const char* name,
1799  ulint flags,
1800  const char* path,
1801  trx_t* trx,
1802  bool commit)
1804 {
1805  dberr_t error;
1806 
1807  pars_info_t* info = pars_info_create();
1808 
1809  ut_a(space > TRX_SYS_SPACE);
1810 
1811  pars_info_add_int4_literal(info, "space", space);
1812 
1813  pars_info_add_str_literal(info, "name", name);
1814 
1815  pars_info_add_int4_literal(info, "flags", flags);
1816 
1817  pars_info_add_str_literal(info, "path", path);
1818 
1819  error = que_eval_sql(info,
1820  "PROCEDURE P () IS\n"
1821  "BEGIN\n"
1822  "INSERT INTO SYS_TABLESPACES VALUES"
1823  "(:space, :name, :flags);\n"
1824  "INSERT INTO SYS_DATAFILES VALUES"
1825  "(:space, :path);\n"
1826  "END;\n",
1827  FALSE, trx);
1828 
1829  if (error != DB_SUCCESS) {
1830  return(error);
1831  }
1832 
1833  if (commit) {
1834  trx->op_info = "committing tablespace and datafile definition";
1835  trx_commit(trx);
1836  }
1837 
1838  trx->op_info = "";
1839 
1840  return(error);
1841 }