Drizzled Public API Documentation

dict0load.cc
1 /*****************************************************************************
2 
3 Copyright (C) 1996, 2010, Innobase Oy. 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., 51 Franklin
15 St, Fifth Floor, Boston, MA 02110-1301 USA
16 
17 *****************************************************************************/
18 
19 /**************************************************/
27 #if defined(BUILD_DRIZZLE)
28 # include "config.h"
29 #else
30 # include "mysql_version.h"
31 #endif /* BUILD_DRIZZLE */
32 #include "dict0load.h"
33 
34 #ifdef UNIV_NONINL
35 #include "dict0load.ic"
36 #endif
37 
38 #include "btr0pcur.h"
39 #include "btr0btr.h"
40 #include "page0page.h"
41 #include "mach0data.h"
42 #include "dict0dict.h"
43 #include "dict0boot.h"
44 #include "rem0cmp.h"
45 #include "srv0start.h"
46 #include "srv0srv.h"
47 #include "ha_prototypes.h" /* innobase_casedn_str() */
48 
49 
51 static const char* SYSTEM_TABLE_NAME[] = {
52  "SYS_TABLES",
53  "SYS_INDEXES",
54  "SYS_COLUMNS",
55  "SYS_FIELDS",
56  "SYS_FOREIGN",
57  "SYS_FOREIGN_COLS"
58 };
59 /****************************************************************/
62 static
63 ibool
64 name_of_col_is(
65 /*===========*/
66  const dict_table_t* table,
67  const dict_index_t* index,
68  ulint i,
69  const char* name)
70 {
72  dict_index_get_nth_field(
73  index, i)));
74 
75  return(strcmp(name, dict_table_get_col_name(table, tmp)) == 0);
76 }
77 
78 /********************************************************************/
82 UNIV_INTERN
83 char*
85 /*============================*/
86  const char* name)
87 {
88  dict_table_t* sys_tables;
89  btr_pcur_t pcur;
90  dict_index_t* sys_index;
91  dtuple_t* tuple;
92  mem_heap_t* heap;
93  dfield_t* dfield;
94  const rec_t* rec;
95  const byte* field;
96  ulint len;
97  mtr_t mtr;
98 
99  ut_ad(mutex_own(&(dict_sys->mutex)));
100 
101  heap = mem_heap_create(1000);
102 
103  mtr_start(&mtr);
104 
105  sys_tables = dict_table_get_low("SYS_TABLES");
106  sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
107  ut_a(!dict_table_is_comp(sys_tables));
108 
109  tuple = dtuple_create(heap, 1);
110  dfield = dtuple_get_nth_field(tuple, 0);
111 
112  dfield_set_data(dfield, name, ut_strlen(name));
113  dict_index_copy_types(tuple, sys_index, 1);
114 
115  btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
116  BTR_SEARCH_LEAF, &pcur, &mtr);
117 loop:
118  rec = btr_pcur_get_rec(&pcur);
119 
120  if (!btr_pcur_is_on_user_rec(&pcur)) {
121  /* Not found */
122 
123  btr_pcur_close(&pcur);
124  mtr_commit(&mtr);
125  mem_heap_free(heap);
126 
127  return(NULL);
128  }
129 
130  field = rec_get_nth_field_old(rec, 0, &len);
131 
132  if (len < strlen(name)
133  || ut_memcmp(name, field, strlen(name)) != 0) {
134  /* Not found */
135 
136  btr_pcur_close(&pcur);
137  mtr_commit(&mtr);
138  mem_heap_free(heap);
139 
140  return(NULL);
141  }
142 
143  if (!rec_get_deleted_flag(rec, 0)) {
144 
145  /* We found one */
146 
147  char* table_name = mem_strdupl((char*) field, len);
148 
149  btr_pcur_close(&pcur);
150  mtr_commit(&mtr);
151  mem_heap_free(heap);
152 
153  return(table_name);
154  }
155 
156  btr_pcur_move_to_next_user_rec(&pcur, &mtr);
157 
158  goto loop;
159 }
160 
161 /********************************************************************/
164 UNIV_INTERN
165 void
167 /*============*/
168 {
169  dict_table_t* table;
170  btr_pcur_t pcur;
171  const rec_t* rec;
172  mem_heap_t* heap;
173  mtr_t mtr;
174 
175  /* Enlarge the fatal semaphore wait timeout during the InnoDB table
176  monitor printout */
177 
178  mutex_enter(&kernel_mutex);
179  srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
180  mutex_exit(&kernel_mutex);
181 
182  heap = mem_heap_create(1000);
183  mutex_enter(&(dict_sys->mutex));
184 
185  mtr_start(&mtr);
186 
187  rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
188 
189  while (rec) {
190  const char* err_msg;
191 
192  err_msg = dict_process_sys_tables_rec(
193  heap, rec, &table,
194  static_cast<dict_table_info>(DICT_TABLE_LOAD_FROM_CACHE
196 
197  mtr_commit(&mtr);
198 
199  if (!err_msg) {
200  dict_table_print_low(table);
201  } else {
202  ut_print_timestamp(stderr);
203  fprintf(stderr, " InnoDB: %s\n", err_msg);
204  }
205 
206  mem_heap_empty(heap);
207 
208  mtr_start(&mtr);
209  rec = dict_getnext_system(&pcur, &mtr);
210  }
211 
212  mtr_commit(&mtr);
213  mutex_exit(&(dict_sys->mutex));
214  mem_heap_free(heap);
215 
216  /* Restore the fatal semaphore wait timeout */
217  mutex_enter(&kernel_mutex);
218  srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
219  mutex_exit(&kernel_mutex);
220 }
221 
222 
223 /********************************************************************/
226 static
227 const rec_t*
228 dict_getnext_system_low(
229 /*====================*/
230  btr_pcur_t* pcur,
232  mtr_t* mtr)
233 {
234  rec_t* rec = NULL;
235 
236  while (!rec || rec_get_deleted_flag(rec, 0)) {
238 
239  rec = btr_pcur_get_rec(pcur);
240 
241  if (!btr_pcur_is_on_user_rec(pcur)) {
242  /* end of index */
243  btr_pcur_close(pcur);
244 
245  return(NULL);
246  }
247  }
248 
249  /* Get a record, let's save the position */
250  btr_pcur_store_position(pcur, mtr);
251 
252  return(rec);
253 }
254 
255 /********************************************************************/
258 UNIV_INTERN
259 const rec_t*
261 /*==================*/
262  btr_pcur_t* pcur,
264  mtr_t* mtr,
265  dict_system_id_t system_id)
266 {
267  dict_table_t* system_table;
268  dict_index_t* clust_index;
269  const rec_t* rec;
270 
271  ut_a(system_id < SYS_NUM_SYSTEM_TABLES);
272 
273  system_table = dict_table_get_low(SYSTEM_TABLE_NAME[system_id]);
274 
275  clust_index = UT_LIST_GET_FIRST(system_table->indexes);
276 
277  btr_pcur_open_at_index_side(TRUE, clust_index, BTR_SEARCH_LEAF, pcur,
278  TRUE, mtr);
279 
280  rec = dict_getnext_system_low(pcur, mtr);
281 
282  return(rec);
283 }
284 
285 /********************************************************************/
288 UNIV_INTERN
289 const rec_t*
291 /*================*/
292  btr_pcur_t* pcur,
294  mtr_t* mtr)
295 {
296  const rec_t* rec;
297 
298  /* Restore the position */
299  btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, mtr);
300 
301  /* Get the next record */
302  rec = dict_getnext_system_low(pcur, mtr);
303 
304  return(rec);
305 }
306 /********************************************************************/
311 UNIV_INTERN
312 const char*
314 /*========================*/
315  mem_heap_t* heap,
316  const rec_t* rec,
317  dict_table_t** table,
318  dict_table_info_t status)
322 {
323  ulint len;
324  const char* field;
325  const char* err_msg = NULL;
326  char* table_name;
327 
328  field = (const char*) rec_get_nth_field_old(rec, 0, &len);
329 
330  ut_a(!rec_get_deleted_flag(rec, 0));
331 
332  /* Get the table name */
333  table_name = mem_heap_strdupl(heap, (const char*)field, len);
334 
335  /* If DICT_TABLE_LOAD_FROM_CACHE is set, first check
336  whether there is cached dict_table_t struct first */
337  if (status & DICT_TABLE_LOAD_FROM_CACHE) {
338  *table = dict_table_get_low(table_name);
339 
340  if (!(*table)) {
341  err_msg = "Table not found in cache";
342  }
343  } else {
344  err_msg = dict_load_table_low(table_name, rec, table);
345  }
346 
347  if (err_msg) {
348  return(err_msg);
349  }
350 
351  if ((status & DICT_TABLE_UPDATE_STATS)
352  && dict_table_get_first_index(*table)) {
353 
354  /* Update statistics if DICT_TABLE_UPDATE_STATS
355  is set */
356  dict_update_statistics(*table,
357  FALSE /* update even if
358  initialized */);
359  }
360 
361  return(NULL);
362 }
363 
364 /********************************************************************/
369 UNIV_INTERN
370 const char*
372 /*=========================*/
373  mem_heap_t* heap,
374  const rec_t* rec,
375  dict_index_t* index,
376  table_id_t* table_id)
377 {
378  const char* err_msg;
379  byte* buf;
380 
381  buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
382 
383  /* Parse the record, and get "dict_index_t" struct filled */
384  err_msg = dict_load_index_low(buf, NULL,
385  heap, rec, FALSE, &index);
386 
387  *table_id = mach_read_from_8(buf);
388 
389  return(err_msg);
390 }
391 /********************************************************************/
395 UNIV_INTERN
396 const char*
398 /*=========================*/
399  mem_heap_t* heap,
400  const rec_t* rec,
401  dict_col_t* column,
402  table_id_t* table_id,
403  const char** col_name)
404 {
405  const char* err_msg;
406 
407  /* Parse the record, and get "dict_col_t" struct filled */
408  err_msg = dict_load_column_low(NULL, heap, column,
409  table_id, col_name, rec);
410 
411  return(err_msg);
412 }
413 /********************************************************************/
417 UNIV_INTERN
418 const char*
420 /*========================*/
421  mem_heap_t* heap,
422  const rec_t* rec,
423  dict_field_t* sys_field,
425  ulint* pos,
426  index_id_t* index_id,
427  index_id_t last_id)
428 {
429  byte* buf;
430  byte* last_index_id;
431  const char* err_msg;
432 
433  buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
434 
435  last_index_id = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
436  mach_write_to_8(last_index_id, last_id);
437 
438  err_msg = dict_load_field_low(buf, NULL, sys_field,
439  pos, last_index_id, heap, rec);
440 
441  *index_id = mach_read_from_8(buf);
442 
443  return(err_msg);
444 
445 }
446 
447 /********************************************************************/
452 UNIV_INTERN
453 const char*
455 /*=========================*/
456  mem_heap_t* heap,
457  const rec_t* rec,
458  dict_foreign_t* foreign)
460 {
461  ulint len;
462  const byte* field;
463  ulint n_fields_and_type;
464 
465  if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
466  return("delete-marked record in SYS_FOREIGN");
467  }
468 
469  if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 6)) {
470  return("wrong number of columns in SYS_FOREIGN record");
471  }
472 
473  field = rec_get_nth_field_old(rec, 0/*ID*/, &len);
474  if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
475 err_len:
476  return("incorrect column length in SYS_FOREIGN");
477  }
478 
479  /* This recieves a dict_foreign_t* that points to a stack variable.
480  So mem_heap_free(foreign->heap) is not used as elsewhere.
481  Since the heap used here is freed elsewhere, foreign->heap
482  is not assigned. */
483  foreign->id = mem_heap_strdupl(heap, (const char*) field, len);
484 
485  rec_get_nth_field_offs_old(rec, 1/*DB_TRX_ID*/, &len);
486  if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
487  goto err_len;
488  }
489  rec_get_nth_field_offs_old(rec, 2/*DB_ROLL_PTR*/, &len);
490  if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
491  goto err_len;
492  }
493 
494  /* The _lookup versions of the referenced and foreign table names
495  are not assigned since they are not used in this dict_foreign_t */
496 
497  field = rec_get_nth_field_old(rec, 3/*FOR_NAME*/, &len);
498  if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
499  goto err_len;
500  }
502  heap, (const char*) field, len);
503 
504  field = rec_get_nth_field_old(rec, 4/*REF_NAME*/, &len);
505  if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
506  goto err_len;
507  }
509  heap, (const char*) field, len);
510 
511  field = rec_get_nth_field_old(rec, 5/*N_COLS*/, &len);
512  if (UNIV_UNLIKELY(len != 4)) {
513  goto err_len;
514  }
515  n_fields_and_type = mach_read_from_4(field);
516 
517  foreign->type = (unsigned int) (n_fields_and_type >> 24);
518  foreign->n_fields = (unsigned int) (n_fields_and_type & 0x3FFUL);
519 
520  return(NULL);
521 }
522 
523 /********************************************************************/
527 UNIV_INTERN
528 const char*
530 /*=============================*/
531  mem_heap_t* heap,
532  const rec_t* rec,
533  const char** name,
534  const char** for_col_name,
535  const char** ref_col_name,
537  ulint* pos)
538 {
539  ulint len;
540  const byte* field;
541 
542  if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
543  return("delete-marked record in SYS_FOREIGN_COLS");
544  }
545 
546  if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 6)) {
547  return("wrong number of columns in SYS_FOREIGN_COLS record");
548  }
549 
550  field = rec_get_nth_field_old(rec, 0/*ID*/, &len);
551  if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
552 err_len:
553  return("incorrect column length in SYS_FOREIGN_COLS");
554  }
555  *name = mem_heap_strdupl(heap, (char*) field, len);
556 
557  field = rec_get_nth_field_old(rec, 1/*POS*/, &len);
558  if (UNIV_UNLIKELY(len != 4)) {
559  goto err_len;
560  }
561  *pos = mach_read_from_4(field);
562 
563  rec_get_nth_field_offs_old(rec, 2/*DB_TRX_ID*/, &len);
564  if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
565  goto err_len;
566  }
567  rec_get_nth_field_offs_old(rec, 3/*DB_ROLL_PTR*/, &len);
568  if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
569  goto err_len;
570  }
571 
572  field = rec_get_nth_field_old(rec, 4/*FOR_COL_NAME*/, &len);
573  if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
574  goto err_len;
575  }
576  *for_col_name = mem_heap_strdupl(heap, (char*) field, len);
577 
578  field = rec_get_nth_field_old(rec, 5/*REF_COL_NAME*/, &len);
579  if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
580  goto err_len;
581  }
582  *ref_col_name = mem_heap_strdupl(heap, (char*) field, len);
583 
584  return(NULL);
585 }
586 
587 /*
588  Send data to callback function .
589 */
590 
591 UNIV_INTERN void dict_print_with_callback(dict_print_callback func, void *func_arg)
592 {
593  dict_table_t* sys_tables;
594  dict_index_t* sys_index;
595  btr_pcur_t pcur;
596  const rec_t* rec;
597  const byte* field;
598  ulint len;
599  mtr_t mtr;
600 
601  /* Enlarge the fatal semaphore wait timeout during the InnoDB table
602  monitor printout */
603 
604  mutex_enter(&kernel_mutex);
605  srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
606  mutex_exit(&kernel_mutex);
607 
608  mutex_enter(&(dict_sys->mutex));
609 
610  mtr_start(&mtr);
611 
612  sys_tables = dict_table_get_low("SYS_TABLES");
613  sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
614 
615  btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
616  TRUE, &mtr);
617 loop:
618  btr_pcur_move_to_next_user_rec(&pcur, &mtr);
619 
620  rec = btr_pcur_get_rec(&pcur);
621 
622  if (!btr_pcur_is_on_user_rec(&pcur)) {
623  /* end of index */
624 
625  btr_pcur_close(&pcur);
626  mtr_commit(&mtr);
627 
628  mutex_exit(&(dict_sys->mutex));
629 
630  /* Restore the fatal semaphore wait timeout */
631 
632  mutex_enter(&kernel_mutex);
633  srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
634  mutex_exit(&kernel_mutex);
635 
636  return;
637  }
638 
639  field = rec_get_nth_field_old(rec, 0, &len);
640 
641  if (!rec_get_deleted_flag(rec, 0)) {
642 
643  /* We found one */
644 
645  char* table_name = mem_strdupl((char*) field, len);
646 
647  btr_pcur_store_position(&pcur, &mtr);
648 
649  mtr_commit(&mtr);
650 
651  func(func_arg, table_name);
652  mem_free(table_name);
653 
654  mtr_start(&mtr);
655 
656  btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
657  }
658 
659  goto loop;
660 }
661 
662 /********************************************************************/
666 static
667 ulint
668 dict_sys_tables_get_flags(
669 /*======================*/
670  const rec_t* rec)
671 {
672  const byte* field;
673  ulint len;
674  ulint n_cols;
675  ulint flags;
676 
677  field = rec_get_nth_field_old(rec, 5, &len);
678  ut_a(len == 4);
679 
680  flags = mach_read_from_4(field);
681 
682  if (UNIV_LIKELY(flags == DICT_TABLE_ORDINARY)) {
683  return(0);
684  }
685 
686  field = rec_get_nth_field_old(rec, 4/*N_COLS*/, &len);
687  n_cols = mach_read_from_4(field);
688 
689  if (UNIV_UNLIKELY(!(n_cols & 0x80000000UL))) {
690  /* New file formats require ROW_FORMAT=COMPACT. */
691  return(ULINT_UNDEFINED);
692  }
693 
694  switch (flags & (DICT_TF_FORMAT_MASK | DICT_TF_COMPACT)) {
695  default:
698  /* flags should be DICT_TABLE_ORDINARY,
699  or DICT_TF_FORMAT_MASK should be nonzero. */
700  return(ULINT_UNDEFINED);
701 
703 #if DICT_TF_FORMAT_MAX > DICT_TF_FORMAT_ZIP
704 # error "missing case labels for DICT_TF_FORMAT_ZIP .. DICT_TF_FORMAT_MAX"
705 #endif
706  /* We support this format. */
707  break;
708  }
709 
710  if (UNIV_UNLIKELY((flags & DICT_TF_ZSSIZE_MASK)
711  > (DICT_TF_ZSSIZE_MAX << DICT_TF_ZSSIZE_SHIFT))) {
712  /* Unsupported compressed page size. */
713  return(ULINT_UNDEFINED);
714  }
715 
716  if (UNIV_UNLIKELY(flags & (SIZE_MAX << DICT_TF_BITS))) {
717  /* Some unused bits are set. */
718  return(ULINT_UNDEFINED);
719  }
720 
721  return(flags);
722 }
723 
724 /********************************************************************/
732 UNIV_INTERN
733 void
735 /*====================================*/
736  ibool in_crash_recovery)
737 {
738  dict_table_t* sys_tables;
739  dict_index_t* sys_index;
740  btr_pcur_t pcur;
741  const rec_t* rec;
742  ulint max_space_id;
743  mtr_t mtr;
744 
745  mutex_enter(&(dict_sys->mutex));
746 
747  mtr_start(&mtr);
748 
749  sys_tables = dict_table_get_low("SYS_TABLES");
750  sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
751  ut_a(!dict_table_is_comp(sys_tables));
752 
753  max_space_id = mtr_read_ulint(dict_hdr_get(&mtr)
754  + DICT_HDR_MAX_SPACE_ID,
755  MLOG_4BYTES, &mtr);
756  fil_set_max_space_id_if_bigger(max_space_id);
757 
758  btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
759  TRUE, &mtr);
760 loop:
761  btr_pcur_move_to_next_user_rec(&pcur, &mtr);
762 
763  rec = btr_pcur_get_rec(&pcur);
764 
765  if (!btr_pcur_is_on_user_rec(&pcur)) {
766  /* end of index */
767 
768  btr_pcur_close(&pcur);
769  mtr_commit(&mtr);
770 
771  /* We must make the tablespace cache aware of the biggest
772  known space id */
773 
774  /* printf("Biggest space id in data dictionary %lu\n",
775  max_space_id); */
776  fil_set_max_space_id_if_bigger(max_space_id);
777 
778  mutex_exit(&(dict_sys->mutex));
779 
780  return;
781  }
782 
783  if (!rec_get_deleted_flag(rec, 0)) {
784 
785  /* We found one */
786  const byte* field;
787  ulint len;
788  ulint space_id;
789  ulint flags;
790  char* name;
791 
792  field = rec_get_nth_field_old(rec, 0, &len);
793  name = mem_strdupl((char*) field, len);
794 
795  flags = dict_sys_tables_get_flags(rec);
796  if (UNIV_UNLIKELY(flags == ULINT_UNDEFINED)) {
797 
798  field = rec_get_nth_field_old(rec, 5, &len);
799  flags = mach_read_from_4(field);
800 
801  ut_print_timestamp(stderr);
802  fputs(" InnoDB: Error: table ", stderr);
803  ut_print_filename(stderr, name);
804  fprintf(stderr, "\n"
805  "InnoDB: in InnoDB data dictionary"
806  " has unknown type %lx.\n",
807  (ulong) flags);
808 
809  goto loop;
810  }
811 
812  field = rec_get_nth_field_old(rec, 9, &len);
813  ut_a(len == 4);
814 
815  space_id = mach_read_from_4(field);
816 
817  btr_pcur_store_position(&pcur, &mtr);
818 
819  mtr_commit(&mtr);
820 
821  if (space_id == 0) {
822  /* The system tablespace always exists. */
823  } else if (in_crash_recovery) {
824  /* Check that the tablespace (the .ibd file) really
825  exists; print a warning to the .err log if not.
826  Do not print warnings for temporary tables. */
827  ibool is_temp;
828 
829  field = rec_get_nth_field_old(rec, 4, &len);
830  if (0x80000000UL & mach_read_from_4(field)) {
831  /* ROW_FORMAT=COMPACT: read the is_temp
832  flag from SYS_TABLES.MIX_LEN. */
833  field = rec_get_nth_field_old(rec, 7, &len);
834  is_temp = mach_read_from_4(field)
836  } else {
837  /* For tables created with old versions
838  of InnoDB, SYS_TABLES.MIX_LEN may contain
839  garbage. Such tables would always be
840  in ROW_FORMAT=REDUNDANT. Pretend that
841  all such tables are non-temporary. That is,
842  do not suppress error printouts about
843  temporary tables not being found. */
844  is_temp = FALSE;
845  }
846 
848  space_id, name, is_temp, TRUE, !is_temp);
849  } else {
850  /* It is a normal database startup: create the space
851  object and check that the .ibd file exists. */
852 
853  fil_open_single_table_tablespace(FALSE, space_id,
854  flags, name);
855  }
856 
857  mem_free(name);
858 
859  if (space_id > max_space_id) {
860  max_space_id = space_id;
861  }
862 
863  mtr_start(&mtr);
864 
865  btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
866  }
867 
868  goto loop;
869 }
870 
871 /********************************************************************/
875 UNIV_INTERN
876 const char*
878 /*=================*/
879  dict_table_t* table,
883  mem_heap_t* heap,
885  dict_col_t* column,
887  table_id_t* table_id,
888  const char** col_name,
889  const rec_t* rec)
890 {
891  char* name;
892  const byte* field;
893  ulint len;
894  ulint mtype;
895  ulint prtype;
896  ulint col_len;
897  ulint pos = 0;
898 
899  ut_ad(table || column);
900 
901  if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
902  return("delete-marked record in SYS_COLUMNS");
903  }
904 
905  if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 9)) {
906  return("wrong number of columns in SYS_COLUMNS record");
907  }
908 
909  field = rec_get_nth_field_old(rec, 0/*TABLE_ID*/, &len);
910  if (UNIV_UNLIKELY(len != 8)) {
911 err_len:
912  return("incorrect column length in SYS_COLUMNS");
913  }
914 
915  if (table_id) {
916  *table_id = mach_read_from_8(field);
917  } else if (UNIV_UNLIKELY(table->id != mach_read_from_8(field))) {
918  return("SYS_COLUMNS.TABLE_ID mismatch");
919  }
920 
921  field = rec_get_nth_field_old(rec, 1/*POS*/, &len);
922  if (UNIV_UNLIKELY(len != 4)) {
923 
924  goto err_len;
925  }
926 
927  pos = mach_read_from_4(field);
928 
929  if (UNIV_UNLIKELY(table && table->n_def != pos)) {
930  return("SYS_COLUMNS.POS mismatch");
931  }
932 
933  rec_get_nth_field_offs_old(rec, 2/*DB_TRX_ID*/, &len);
934  if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
935  goto err_len;
936  }
937  rec_get_nth_field_offs_old(rec, 3/*DB_ROLL_PTR*/, &len);
938  if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
939  goto err_len;
940  }
941 
942  field = rec_get_nth_field_old(rec, 4/*NAME*/, &len);
943  if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
944  goto err_len;
945  }
946 
947  name = mem_heap_strdupl(heap, (const char*) field, len);
948 
949  if (col_name) {
950  *col_name = name;
951  }
952 
953  field = rec_get_nth_field_old(rec, 5/*MTYPE*/, &len);
954  if (UNIV_UNLIKELY(len != 4)) {
955  goto err_len;
956  }
957 
958  mtype = mach_read_from_4(field);
959 
960  field = rec_get_nth_field_old(rec, 6/*PRTYPE*/, &len);
961  if (UNIV_UNLIKELY(len != 4)) {
962  goto err_len;
963  }
964  prtype = mach_read_from_4(field);
965 
966  if (dtype_get_charset_coll(prtype) == 0
967  && dtype_is_string_type(mtype)) {
968  /* The table was created with < 4.1.2. */
969 
970  if (dtype_is_binary_string_type(mtype, prtype)) {
971  /* Use the binary collation for
972  string columns of binary type. */
973 
974  prtype = dtype_form_prtype(
975  prtype,
976  DATA_MYSQL_BINARY_CHARSET_COLL);
977  } else {
978  /* Use the default charset for
979  other than binary columns. */
980 
981  prtype = dtype_form_prtype(
982  prtype,
983  data_mysql_default_charset_coll);
984  }
985  }
986 
987  field = rec_get_nth_field_old(rec, 7/*LEN*/, &len);
988  if (UNIV_UNLIKELY(len != 4)) {
989  goto err_len;
990  }
991  col_len = mach_read_from_4(field);
992  field = rec_get_nth_field_old(rec, 8/*PREC*/, &len);
993  if (UNIV_UNLIKELY(len != 4)) {
994  goto err_len;
995  }
996 
997  if (!column) {
998  dict_mem_table_add_col(table, heap, name, mtype,
999  prtype, col_len);
1000  } else {
1001  dict_mem_fill_column_struct(column, pos, mtype,
1002  prtype, col_len);
1003  }
1004 
1005  return(NULL);
1006 }
1007 
1008 /********************************************************************/
1010 static
1011 void
1012 dict_load_columns(
1013 /*==============*/
1014  dict_table_t* table,
1015  mem_heap_t* heap)
1017 {
1018  dict_table_t* sys_columns;
1019  dict_index_t* sys_index;
1020  btr_pcur_t pcur;
1021  dtuple_t* tuple;
1022  dfield_t* dfield;
1023  const rec_t* rec;
1024  byte* buf;
1025  ulint i;
1026  mtr_t mtr;
1027 
1028  ut_ad(mutex_own(&(dict_sys->mutex)));
1029 
1030  mtr_start(&mtr);
1031 
1032  sys_columns = dict_table_get_low("SYS_COLUMNS");
1033  sys_index = UT_LIST_GET_FIRST(sys_columns->indexes);
1034  ut_a(!dict_table_is_comp(sys_columns));
1035 
1036  ut_a(name_of_col_is(sys_columns, sys_index, 4, "NAME"));
1037  ut_a(name_of_col_is(sys_columns, sys_index, 8, "PREC"));
1038 
1039  tuple = dtuple_create(heap, 1);
1040  dfield = dtuple_get_nth_field(tuple, 0);
1041 
1042  buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
1043  mach_write_to_8(buf, table->id);
1044 
1045  dfield_set_data(dfield, buf, 8);
1046  dict_index_copy_types(tuple, sys_index, 1);
1047 
1048  btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
1049  BTR_SEARCH_LEAF, &pcur, &mtr);
1050  for (i = 0; i + DATA_N_SYS_COLS < (ulint) table->n_cols; i++) {
1051  const char* err_msg;
1052 
1053  rec = btr_pcur_get_rec(&pcur);
1054 
1055  ut_a(btr_pcur_is_on_user_rec(&pcur));
1056 
1057  err_msg = dict_load_column_low(table, heap, NULL, NULL,
1058  NULL, rec);
1059 
1060  if (err_msg) {
1061  fprintf(stderr, "InnoDB: %s\n", err_msg);
1062  ut_error;
1063  }
1064 
1065  btr_pcur_move_to_next_user_rec(&pcur, &mtr);
1066  }
1067 
1068  btr_pcur_close(&pcur);
1069  mtr_commit(&mtr);
1070 }
1071 
1073 static const char* dict_load_field_del = "delete-marked record in SYS_FIELDS";
1074 
1075 /********************************************************************/
1079 UNIV_INTERN
1080 const char*
1082 /*================*/
1083  byte* index_id,
1086  dict_index_t* index,
1090  dict_field_t* sys_field,
1092  ulint* pos,
1093  byte* last_index_id,
1094  mem_heap_t* heap,
1096  const rec_t* rec)
1097 {
1098  const byte* field;
1099  ulint len;
1100  ulint pos_and_prefix_len;
1101  ulint prefix_len;
1102  ibool first_field;
1103  ulint position;
1104 
1105  /* Either index or sys_field is supplied, not both */
1106  ut_a((!index) || (!sys_field));
1107 
1108  if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
1109  return(dict_load_field_del);
1110  }
1111 
1112  if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 5)) {
1113  return("wrong number of columns in SYS_FIELDS record");
1114  }
1115 
1116  field = rec_get_nth_field_old(rec, 0/*INDEX_ID*/, &len);
1117  if (UNIV_UNLIKELY(len != 8)) {
1118 err_len:
1119  return("incorrect column length in SYS_FIELDS");
1120  }
1121 
1122  if (!index) {
1123  ut_a(last_index_id);
1124  memcpy(index_id, (const char*)field, 8);
1125  first_field = memcmp(index_id, last_index_id, 8);
1126  } else {
1127  first_field = (index->n_def == 0);
1128  if (memcmp(field, index_id, 8)) {
1129  return("SYS_FIELDS.INDEX_ID mismatch");
1130  }
1131  }
1132 
1133  field = rec_get_nth_field_old(rec, 1/*POS*/, &len);
1134  if (UNIV_UNLIKELY(len != 4)) {
1135  goto err_len;
1136  }
1137 
1138  rec_get_nth_field_offs_old(rec, 2/*DB_TRX_ID*/, &len);
1139  if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
1140  goto err_len;
1141  }
1142  rec_get_nth_field_offs_old(rec, 3/*DB_ROLL_PTR*/, &len);
1143  if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
1144  goto err_len;
1145  }
1146 
1147  /* The next field stores the field position in the index and a
1148  possible column prefix length if the index field does not
1149  contain the whole column. The storage format is like this: if
1150  there is at least one prefix field in the index, then the HIGH
1151  2 bytes contain the field number (index->n_def) and the low 2
1152  bytes the prefix length for the field. Otherwise the field
1153  number (index->n_def) is contained in the 2 LOW bytes. */
1154 
1155  pos_and_prefix_len = mach_read_from_4(field);
1156 
1157  if (index && UNIV_UNLIKELY
1158  ((pos_and_prefix_len & 0xFFFFUL) != index->n_def
1159  && (pos_and_prefix_len >> 16 & 0xFFFF) != index->n_def)) {
1160  return("SYS_FIELDS.POS mismatch");
1161  }
1162 
1163  if (first_field || pos_and_prefix_len > 0xFFFFUL) {
1164  prefix_len = pos_and_prefix_len & 0xFFFFUL;
1165  position = (pos_and_prefix_len & 0xFFFF0000UL) >> 16;
1166  } else {
1167  prefix_len = 0;
1168  position = pos_and_prefix_len & 0xFFFFUL;
1169  }
1170 
1171  field = rec_get_nth_field_old(rec, 4, &len);
1172  if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
1173  goto err_len;
1174  }
1175 
1176  if (index) {
1178  index, mem_heap_strdupl(heap, (const char*) field, len),
1179  prefix_len);
1180  } else {
1181  ut_a(sys_field);
1182  ut_a(pos);
1183 
1184  sys_field->name = mem_heap_strdupl(
1185  heap, (const char*) field, len);
1186  sys_field->prefix_len = prefix_len;
1187  *pos = position;
1188  }
1189 
1190  return(NULL);
1191 }
1192 
1193 /********************************************************************/
1196 static
1197 ulint
1198 dict_load_fields(
1199 /*=============*/
1200  dict_index_t* index,
1201  mem_heap_t* heap)
1202 {
1203  dict_table_t* sys_fields;
1204  dict_index_t* sys_index;
1205  btr_pcur_t pcur;
1206  dtuple_t* tuple;
1207  dfield_t* dfield;
1208  const rec_t* rec;
1209  byte* buf;
1210  ulint i;
1211  mtr_t mtr;
1212  ulint error;
1213 
1214  ut_ad(mutex_own(&(dict_sys->mutex)));
1215 
1216  mtr_start(&mtr);
1217 
1218  sys_fields = dict_table_get_low("SYS_FIELDS");
1219  sys_index = UT_LIST_GET_FIRST(sys_fields->indexes);
1220  ut_a(!dict_table_is_comp(sys_fields));
1221  ut_a(name_of_col_is(sys_fields, sys_index, 4, "COL_NAME"));
1222 
1223  tuple = dtuple_create(heap, 1);
1224  dfield = dtuple_get_nth_field(tuple, 0);
1225 
1226  buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
1227  mach_write_to_8(buf, index->id);
1228 
1229  dfield_set_data(dfield, buf, 8);
1230  dict_index_copy_types(tuple, sys_index, 1);
1231 
1232  btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
1233  BTR_SEARCH_LEAF, &pcur, &mtr);
1234  for (i = 0; i < index->n_fields; i++) {
1235  const char* err_msg;
1236 
1237  rec = btr_pcur_get_rec(&pcur);
1238 
1239  ut_a(btr_pcur_is_on_user_rec(&pcur));
1240 
1241  err_msg = dict_load_field_low(buf, index, NULL, NULL, NULL,
1242  heap, rec);
1243 
1244  if (err_msg == dict_load_field_del) {
1245  /* There could be delete marked records in
1246  SYS_FIELDS because SYS_FIELDS.INDEX_ID can be
1247  updated by ALTER TABLE ADD INDEX. */
1248 
1249  goto next_rec;
1250  } else if (err_msg) {
1251  fprintf(stderr, "InnoDB: %s\n", err_msg);
1252  error = DB_CORRUPTION;
1253  goto func_exit;
1254  }
1255 next_rec:
1256  btr_pcur_move_to_next_user_rec(&pcur, &mtr);
1257  }
1258 
1259  error = DB_SUCCESS;
1260 func_exit:
1261  btr_pcur_close(&pcur);
1262  mtr_commit(&mtr);
1263  return(error);
1264 }
1265 
1267 static const char* dict_load_index_del = "delete-marked record in SYS_INDEXES";
1269 static const char* dict_load_index_id_err = "SYS_INDEXES.TABLE_ID mismatch";
1270 
1271 /********************************************************************/
1277 UNIV_INTERN
1278 const char*
1280 /*================*/
1281  byte* table_id,
1284  const char* table_name,
1285  mem_heap_t* heap,
1286  const rec_t* rec,
1287  ibool allocate,
1290  dict_index_t** index)
1291 {
1292  const byte* field;
1293  ulint len;
1294  ulint name_len;
1295  char* name_buf;
1296  index_id_t id;
1297  ulint n_fields;
1298  ulint type;
1299  ulint space;
1300 
1301  if (allocate) {
1302  /* If allocate=TRUE, no dict_index_t will
1303  be supplied. Initialize "*index" to NULL */
1304  *index = NULL;
1305  }
1306 
1307  if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
1308  return(dict_load_index_del);
1309  }
1310 
1311  if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 9)) {
1312  return("wrong number of columns in SYS_INDEXES record");
1313  }
1314 
1315  field = rec_get_nth_field_old(rec, 0/*TABLE_ID*/, &len);
1316  if (UNIV_UNLIKELY(len != 8)) {
1317 err_len:
1318  return("incorrect column length in SYS_INDEXES");
1319  }
1320 
1321  if (!allocate) {
1322  /* We are reading a SYS_INDEXES record. Copy the table_id */
1323  memcpy(table_id, (const char*)field, 8);
1324  } else if (memcmp(field, table_id, 8)) {
1325  /* Caller supplied table_id, verify it is the same
1326  id as on the index record */
1327  return(dict_load_index_id_err);
1328  }
1329 
1330  field = rec_get_nth_field_old(rec, 1/*ID*/, &len);
1331  if (UNIV_UNLIKELY(len != 8)) {
1332  goto err_len;
1333  }
1334 
1335  id = mach_read_from_8(field);
1336 
1337  rec_get_nth_field_offs_old(rec, 2/*DB_TRX_ID*/, &len);
1338  if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
1339  goto err_len;
1340  }
1341  rec_get_nth_field_offs_old(rec, 3/*DB_ROLL_PTR*/, &len);
1342  if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
1343  goto err_len;
1344  }
1345 
1346  field = rec_get_nth_field_old(rec, 4/*NAME*/, &name_len);
1347  if (UNIV_UNLIKELY(name_len == UNIV_SQL_NULL)) {
1348  goto err_len;
1349  }
1350 
1351  name_buf = mem_heap_strdupl(heap, (const char*) field,
1352  name_len);
1353 
1354  field = rec_get_nth_field_old(rec, 5/*N_FIELDS*/, &len);
1355  if (UNIV_UNLIKELY(len != 4)) {
1356  goto err_len;
1357  }
1358  n_fields = mach_read_from_4(field);
1359 
1360  field = rec_get_nth_field_old(rec, 6/*TYPE*/, &len);
1361  if (UNIV_UNLIKELY(len != 4)) {
1362  goto err_len;
1363  }
1364  type = mach_read_from_4(field);
1365 
1366  field = rec_get_nth_field_old(rec, 7/*SPACE*/, &len);
1367  if (UNIV_UNLIKELY(len != 4)) {
1368  goto err_len;
1369  }
1370  space = mach_read_from_4(field);
1371 
1372  field = rec_get_nth_field_old(rec, 8/*PAGE_NO*/, &len);
1373  if (UNIV_UNLIKELY(len != 4)) {
1374  goto err_len;
1375  }
1376 
1377  if (allocate) {
1378  *index = dict_mem_index_create(table_name, name_buf,
1379  space, type, n_fields);
1380  } else {
1381  ut_a(*index);
1382 
1383  dict_mem_fill_index_struct(*index, NULL, NULL, name_buf,
1384  space, type, n_fields);
1385  }
1386 
1387  (*index)->id = id;
1388  (*index)->page = mach_read_from_4(field);
1389  ut_ad((*index)->page);
1390 
1391  return(NULL);
1392 }
1393 
1394 /********************************************************************/
1399 static
1400 ulint
1401 dict_load_indexes(
1402 /*==============*/
1403  dict_table_t* table,
1404  mem_heap_t* heap,
1405  dict_err_ignore_t ignore_err)
1408 {
1409  dict_table_t* sys_indexes;
1410  dict_index_t* sys_index;
1411  btr_pcur_t pcur;
1412  dtuple_t* tuple;
1413  dfield_t* dfield;
1414  const rec_t* rec;
1415  byte* buf;
1416  mtr_t mtr;
1417  ulint error = DB_SUCCESS;
1418 
1419  ut_ad(mutex_own(&(dict_sys->mutex)));
1420 
1421  mtr_start(&mtr);
1422 
1423  sys_indexes = dict_table_get_low("SYS_INDEXES");
1424  sys_index = UT_LIST_GET_FIRST(sys_indexes->indexes);
1425  ut_a(!dict_table_is_comp(sys_indexes));
1426  ut_a(name_of_col_is(sys_indexes, sys_index, 4, "NAME"));
1427  ut_a(name_of_col_is(sys_indexes, sys_index, 8, "PAGE_NO"));
1428 
1429  tuple = dtuple_create(heap, 1);
1430  dfield = dtuple_get_nth_field(tuple, 0);
1431 
1432  buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
1433  mach_write_to_8(buf, table->id);
1434 
1435  dfield_set_data(dfield, buf, 8);
1436  dict_index_copy_types(tuple, sys_index, 1);
1437 
1438  btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
1439  BTR_SEARCH_LEAF, &pcur, &mtr);
1440  for (;;) {
1441  dict_index_t* index = NULL;
1442  const char* err_msg;
1443 
1444  if (!btr_pcur_is_on_user_rec(&pcur)) {
1445 
1446  break;
1447  }
1448 
1449  rec = btr_pcur_get_rec(&pcur);
1450 
1451  err_msg = dict_load_index_low(buf, table->name, heap, rec,
1452  TRUE, &index);
1453  ut_ad((index == NULL) == (err_msg != NULL));
1454 
1455  if (err_msg == dict_load_index_id_err) {
1456  /* TABLE_ID mismatch means that we have
1457  run out of index definitions for the table. */
1458  break;
1459  } else if (err_msg == dict_load_index_del) {
1460  /* Skip delete-marked records. */
1461  goto next_rec;
1462  } else if (err_msg) {
1463  fprintf(stderr, "InnoDB: %s\n", err_msg);
1464  error = DB_CORRUPTION;
1465  goto func_exit;
1466  }
1467 
1468  ut_ad(index);
1469 
1470  /* We check for unsupported types first, so that the
1471  subsequent checks are relevant for the supported types. */
1472  if (index->type & ~(DICT_CLUSTERED | DICT_UNIQUE)) {
1473 
1474  fprintf(stderr,
1475  "InnoDB: Error: unknown type %lu"
1476  " of index %s of table %s\n",
1477  (ulong) index->type, index->name, table->name);
1478 
1479  error = DB_UNSUPPORTED;
1480  dict_mem_index_free(index);
1481  goto func_exit;
1482  } else if (index->page == FIL_NULL) {
1483 
1484  fprintf(stderr,
1485  "InnoDB: Error: trying to load index %s"
1486  " for table %s\n"
1487  "InnoDB: but the index tree has been freed!\n",
1488  index->name, table->name);
1489 
1490  if (ignore_err & DICT_ERR_IGNORE_INDEX_ROOT) {
1491  /* If caller can tolerate this error,
1492  we will continue to load the index and
1493  let caller deal with this error. However
1494  mark the index and table corrupted */
1495  index->corrupted = TRUE;
1496  table->corrupted = TRUE;
1497  fprintf(stderr,
1498  "InnoDB: Index is corrupt but forcing"
1499  " load into data dictionary\n");
1500  } else {
1501 corrupted:
1502  dict_mem_index_free(index);
1503  error = DB_CORRUPTION;
1504  goto func_exit;
1505  }
1506  } else if (!dict_index_is_clust(index)
1507  && NULL == dict_table_get_first_index(table)) {
1508 
1509  fputs("InnoDB: Error: trying to load index ",
1510  stderr);
1511  ut_print_name(stderr, NULL, FALSE, index->name);
1512  fputs(" for table ", stderr);
1513  ut_print_name(stderr, NULL, TRUE, table->name);
1514  fputs("\nInnoDB: but the first index"
1515  " is not clustered!\n", stderr);
1516 
1517  goto corrupted;
1518  } else if (table->id < DICT_HDR_FIRST_ID
1519  && (dict_index_is_clust(index)
1520  || ((table == dict_sys->sys_tables)
1521  && !strcmp("ID_IND", index->name)))) {
1522 
1523  /* The index was created in memory already at booting
1524  of the database server */
1525  dict_mem_index_free(index);
1526  } else {
1527  dict_load_fields(index, heap);
1528  error = dict_index_add_to_cache(table, index,
1529  index->page, FALSE);
1530  /* The data dictionary tables should never contain
1531  invalid index definitions. If we ignored this error
1532  and simply did not load this index definition, the
1533  .frm file would disagree with the index definitions
1534  inside InnoDB. */
1535  if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
1536 
1537  goto func_exit;
1538  }
1539  }
1540 
1541 next_rec:
1542  btr_pcur_move_to_next_user_rec(&pcur, &mtr);
1543  }
1544 
1545 func_exit:
1546  btr_pcur_close(&pcur);
1547  mtr_commit(&mtr);
1548 
1549  return(error);
1550 }
1551 
1552 /********************************************************************/
1556 UNIV_INTERN
1557 const char*
1559 /*================*/
1560  const char* name,
1561  const rec_t* rec,
1562  dict_table_t** table)
1563 {
1564  const byte* field;
1565  ulint len;
1566  ulint space;
1567  ulint n_cols;
1568  ulint flags;
1569 
1570  if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
1571  return("delete-marked record in SYS_TABLES");
1572  }
1573 
1574  if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 10)) {
1575  return("wrong number of columns in SYS_TABLES record");
1576  }
1577 
1578  rec_get_nth_field_offs_old(rec, 0/*NAME*/, &len);
1579  if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
1580 err_len:
1581  return("incorrect column length in SYS_TABLES");
1582  }
1583  rec_get_nth_field_offs_old(rec, 1/*DB_TRX_ID*/, &len);
1584  if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
1585  goto err_len;
1586  }
1587  rec_get_nth_field_offs_old(rec, 2/*DB_ROLL_PTR*/, &len);
1588  if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
1589  goto err_len;
1590  }
1591 
1592  rec_get_nth_field_offs_old(rec, 3/*ID*/, &len);
1593  if (UNIV_UNLIKELY(len != 8)) {
1594  goto err_len;
1595  }
1596 
1597  field = rec_get_nth_field_old(rec, 4/*N_COLS*/, &len);
1598  if (UNIV_UNLIKELY(len != 4)) {
1599  goto err_len;
1600  }
1601 
1602  n_cols = mach_read_from_4(field);
1603 
1604  rec_get_nth_field_offs_old(rec, 5/*TYPE*/, &len);
1605  if (UNIV_UNLIKELY(len != 4)) {
1606  goto err_len;
1607  }
1608 
1609  rec_get_nth_field_offs_old(rec, 6/*MIX_ID*/, &len);
1610  if (UNIV_UNLIKELY(len != 8)) {
1611  goto err_len;
1612  }
1613 
1614  rec_get_nth_field_offs_old(rec, 7/*MIX_LEN*/, &len);
1615  if (UNIV_UNLIKELY(len != 4)) {
1616  goto err_len;
1617  }
1618 
1619  rec_get_nth_field_offs_old(rec, 8/*CLUSTER_ID*/, &len);
1620  if (UNIV_UNLIKELY(len != UNIV_SQL_NULL)) {
1621  goto err_len;
1622  }
1623 
1624  field = rec_get_nth_field_old(rec, 9/*SPACE*/, &len);
1625 
1626  if (UNIV_UNLIKELY(len != 4)) {
1627  goto err_len;
1628  }
1629 
1630  space = mach_read_from_4(field);
1631 
1632  /* Check if the tablespace exists and has the right name */
1633  if (space != 0) {
1634  flags = dict_sys_tables_get_flags(rec);
1635 
1636  if (UNIV_UNLIKELY(flags == ULINT_UNDEFINED)) {
1637  field = rec_get_nth_field_old(rec, 5/*TYPE*/, &len);
1638  ut_ad(len == 4); /* this was checked earlier */
1639  flags = mach_read_from_4(field);
1640 
1641  ut_print_timestamp(stderr);
1642  fputs(" InnoDB: Error: table ", stderr);
1643  ut_print_filename(stderr, name);
1644  fprintf(stderr, "\n"
1645  "InnoDB: in InnoDB data dictionary"
1646  " has unknown type %lx.\n",
1647  (ulong) flags);
1648  return("incorrect flags in SYS_TABLES");
1649  }
1650  } else {
1651  flags = 0;
1652  }
1653 
1654  /* The high-order bit of N_COLS is the "compact format" flag.
1655  For tables in that format, MIX_LEN may hold additional flags. */
1656  if (n_cols & 0x80000000UL) {
1657  ulint flags2;
1658 
1659  flags |= DICT_TF_COMPACT;
1660 
1661  field = rec_get_nth_field_old(rec, 7, &len);
1662 
1663  if (UNIV_UNLIKELY(len != 4)) {
1664 
1665  goto err_len;
1666  }
1667 
1668  flags2 = mach_read_from_4(field);
1669 
1670  if (flags2 & (SIZE_MAX << (DICT_TF2_BITS - DICT_TF2_SHIFT))) {
1671  ut_print_timestamp(stderr);
1672  fputs(" InnoDB: Warning: table ", stderr);
1673  ut_print_filename(stderr, name);
1674  fprintf(stderr, "\n"
1675  "InnoDB: in InnoDB data dictionary"
1676  " has unknown flags %lx.\n",
1677  (ulong) flags2);
1678 
1679  flags2 &= ~(~0 << (DICT_TF2_BITS - DICT_TF2_SHIFT));
1680  }
1681 
1682  flags |= flags2 << DICT_TF2_SHIFT;
1683  }
1684 
1685  /* See if the tablespace is available. */
1686  *table = dict_mem_table_create(name, space, n_cols & ~0x80000000UL,
1687  flags);
1688 
1689  field = rec_get_nth_field_old(rec, 3/*ID*/, &len);
1690  ut_ad(len == 8); /* this was checked earlier */
1691 
1692  (*table)->id = mach_read_from_8(field);
1693 
1694  (*table)->ibd_file_missing = FALSE;
1695 
1696  return(NULL);
1697 }
1698 
1699 /********************************************************************/
1708 UNIV_INTERN
1709 dict_table_t*
1711 /*============*/
1712  const char* name,
1714  ibool cached,
1715  dict_err_ignore_t ignore_err)
1718 {
1719  dict_table_t* table;
1720  dict_table_t* sys_tables;
1721  btr_pcur_t pcur;
1722  dict_index_t* sys_index;
1723  dtuple_t* tuple;
1724  mem_heap_t* heap;
1725  dfield_t* dfield;
1726  const rec_t* rec;
1727  const byte* field;
1728  ulint len;
1729  ulint err;
1730  const char* err_msg;
1731  mtr_t mtr;
1732 
1733  ut_ad(mutex_own(&(dict_sys->mutex)));
1734 
1735  heap = mem_heap_create(32000);
1736 
1737  mtr_start(&mtr);
1738 
1739  sys_tables = dict_table_get_low("SYS_TABLES");
1740  sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
1741  ut_a(!dict_table_is_comp(sys_tables));
1742  ut_a(name_of_col_is(sys_tables, sys_index, 3, "ID"));
1743  ut_a(name_of_col_is(sys_tables, sys_index, 4, "N_COLS"));
1744  ut_a(name_of_col_is(sys_tables, sys_index, 5, "TYPE"));
1745  ut_a(name_of_col_is(sys_tables, sys_index, 7, "MIX_LEN"));
1746  ut_a(name_of_col_is(sys_tables, sys_index, 9, "SPACE"));
1747 
1748  tuple = dtuple_create(heap, 1);
1749  dfield = dtuple_get_nth_field(tuple, 0);
1750 
1751  dfield_set_data(dfield, name, ut_strlen(name));
1752  dict_index_copy_types(tuple, sys_index, 1);
1753 
1754  btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
1755  BTR_SEARCH_LEAF, &pcur, &mtr);
1756  rec = btr_pcur_get_rec(&pcur);
1757 
1758  if (!btr_pcur_is_on_user_rec(&pcur)
1759  || rec_get_deleted_flag(rec, 0)) {
1760  /* Not found */
1761 err_exit:
1762  btr_pcur_close(&pcur);
1763  mtr_commit(&mtr);
1764  mem_heap_free(heap);
1765 
1766  return(NULL);
1767  }
1768 
1769  field = rec_get_nth_field_old(rec, 0, &len);
1770 
1771  /* Check if the table name in record is the searched one */
1772  if (len != ut_strlen(name) || ut_memcmp(name, field, len) != 0) {
1773 
1774  goto err_exit;
1775  }
1776 
1777  err_msg = dict_load_table_low(name, rec, &table);
1778 
1779  if (err_msg) {
1780 
1781  ut_print_timestamp(stderr);
1782  fprintf(stderr, " InnoDB: %s\n", err_msg);
1783  goto err_exit;
1784  }
1785 
1786  if (table->space == 0) {
1787  /* The system tablespace is always available. */
1789  table->space, name,
1790  (table->flags >> DICT_TF2_SHIFT)
1792  FALSE, FALSE)) {
1793 
1794  if (table->flags & (DICT_TF2_TEMPORARY << DICT_TF2_SHIFT)) {
1795  /* Do not bother to retry opening temporary tables. */
1796  table->ibd_file_missing = TRUE;
1797  } else {
1798  ut_print_timestamp(stderr);
1799  fprintf(stderr,
1800  " InnoDB: error: space object of table ");
1801  ut_print_filename(stderr, name);
1802  fprintf(stderr, ",\n"
1803  "InnoDB: space id %lu did not exist in memory."
1804  " Retrying an open.\n",
1805  (ulong) table->space);
1806  /* Try to open the tablespace */
1808  TRUE, table->space,
1809  table->flags == DICT_TF_COMPACT ? 0 :
1810  table->flags & ~(~0 << DICT_TF_BITS), name)) {
1811  /* We failed to find a sensible
1812  tablespace file */
1813 
1814  table->ibd_file_missing = TRUE;
1815  }
1816  }
1817  }
1818 
1819  btr_pcur_close(&pcur);
1820  mtr_commit(&mtr);
1821 
1822  dict_load_columns(table, heap);
1823 
1824  if (cached) {
1825  dict_table_add_to_cache(table, heap);
1826  } else {
1827  dict_table_add_system_columns(table, heap);
1828  }
1829 
1830  mem_heap_empty(heap);
1831 
1832  err = dict_load_indexes(table, heap, ignore_err);
1833 
1834  /* Initialize table foreign_child value. Its value could be
1835  changed when dict_load_foreigns() is called below */
1836  table->fk_max_recusive_level = 0;
1837 
1838  /* If the force recovery flag is set, we open the table irrespective
1839  of the error condition, since the user may want to dump data from the
1840  clustered index. However we load the foreign key information only if
1841  all indexes were loaded. */
1842  if (!cached) {
1843  } else if (err == DB_SUCCESS) {
1844  err = dict_load_foreigns(table->name, TRUE, TRUE);
1845 
1846  if (err != DB_SUCCESS) {
1848  table = NULL;
1849  } else {
1850  table->fk_max_recusive_level = 0;
1851  }
1852  } else if (!srv_force_recovery) {
1854  table = NULL;
1855  }
1856 #if 0
1857  if (err != DB_SUCCESS && table != NULL) {
1858 
1859  mutex_enter(&dict_foreign_err_mutex);
1860 
1861  ut_print_timestamp(stderr);
1862 
1863  fprintf(stderr,
1864  " InnoDB: Error: could not make a foreign key"
1865  " definition to match\n"
1866  "InnoDB: the foreign key table"
1867  " or the referenced table!\n"
1868  "InnoDB: The data dictionary of InnoDB is corrupt."
1869  " You may need to drop\n"
1870  "InnoDB: and recreate the foreign key table"
1871  " or the referenced table.\n"
1872  "InnoDB: Submit a detailed bug report"
1873  " to http://bugs.mysql.com\n"
1874  "InnoDB: Latest foreign key error printout:\n%s\n",
1875  dict_foreign_err_buf);
1876 
1877  mutex_exit(&dict_foreign_err_mutex);
1878  }
1879 #endif /* 0 */
1880  mem_heap_free(heap);
1881 
1882  return(table);
1883 }
1884 
1885 /***********************************************************************/
1888 UNIV_INTERN
1889 dict_table_t*
1891 /*==================*/
1892  table_id_t table_id)
1893 {
1894  byte id_buf[8];
1895  btr_pcur_t pcur;
1896  mem_heap_t* heap;
1897  dtuple_t* tuple;
1898  dfield_t* dfield;
1899  dict_index_t* sys_table_ids;
1900  dict_table_t* sys_tables;
1901  const rec_t* rec;
1902  const byte* field;
1903  ulint len;
1904  dict_table_t* table;
1905  mtr_t mtr;
1906 
1907  ut_ad(mutex_own(&(dict_sys->mutex)));
1908 
1909  table = NULL;
1910 
1911  table = NULL;
1912 
1913  /* NOTE that the operation of this function is protected by
1914  the dictionary mutex, and therefore no deadlocks can occur
1915  with other dictionary operations. */
1916 
1917  mtr_start(&mtr);
1918  /*---------------------------------------------------*/
1919  /* Get the secondary index based on ID for table SYS_TABLES */
1920  sys_tables = dict_sys->sys_tables;
1921  sys_table_ids = dict_table_get_next_index(
1922  dict_table_get_first_index(sys_tables));
1923  ut_a(!dict_table_is_comp(sys_tables));
1924  heap = mem_heap_create(256);
1925 
1926  tuple = dtuple_create(heap, 1);
1927  dfield = dtuple_get_nth_field(tuple, 0);
1928 
1929  /* Write the table id in byte format to id_buf */
1930  mach_write_to_8(id_buf, table_id);
1931 
1932  dfield_set_data(dfield, id_buf, 8);
1933  dict_index_copy_types(tuple, sys_table_ids, 1);
1934 
1935  btr_pcur_open_on_user_rec(sys_table_ids, tuple, PAGE_CUR_GE,
1936  BTR_SEARCH_LEAF, &pcur, &mtr);
1937  rec = btr_pcur_get_rec(&pcur);
1938 
1939  if (!btr_pcur_is_on_user_rec(&pcur)) {
1940  /* Not found */
1941  goto func_exit;
1942  }
1943 
1944  /* Find the first record that is not delete marked */
1945  while (rec_get_deleted_flag(rec, 0)) {
1946  if (!btr_pcur_move_to_next_user_rec(&pcur, &mtr)) {
1947  goto func_exit;
1948  }
1949  rec = btr_pcur_get_rec(&pcur);
1950  }
1951 
1952  /*---------------------------------------------------*/
1953  /* Now we have the record in the secondary index containing the
1954  table ID and NAME */
1955 
1956  rec = btr_pcur_get_rec(&pcur);
1957  field = rec_get_nth_field_old(rec, 0, &len);
1958  ut_ad(len == 8);
1959 
1960  /* Check if the table id in record is the one searched for */
1961  if (table_id != mach_read_from_8(field)) {
1962  goto func_exit;
1963  }
1964 
1965  /* Now we get the table name from the record */
1966  field = rec_get_nth_field_old(rec, 1, &len);
1967  /* Load the table definition to memory */
1968  table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len),
1969  TRUE, DICT_ERR_IGNORE_NONE);
1970 func_exit:
1971  btr_pcur_close(&pcur);
1972  mtr_commit(&mtr);
1973  mem_heap_free(heap);
1974 
1975  return(table);
1976 }
1977 
1978 /********************************************************************/
1982 UNIV_INTERN
1983 void
1985 /*================*/
1986  dict_table_t* table)
1987 {
1988  mem_heap_t* heap;
1989 
1990  ut_ad(mutex_own(&(dict_sys->mutex)));
1991 
1992  heap = mem_heap_create(1000);
1993 
1994  dict_load_indexes(table, heap, DICT_ERR_IGNORE_NONE);
1995 
1996  mem_heap_free(heap);
1997 }
1998 
1999 /********************************************************************/
2001 static
2002 void
2003 dict_load_foreign_cols(
2004 /*===================*/
2005  const char* id,
2007  dict_foreign_t* foreign)
2008 {
2009  dict_table_t* sys_foreign_cols;
2010  dict_index_t* sys_index;
2011  btr_pcur_t pcur;
2012  dtuple_t* tuple;
2013  dfield_t* dfield;
2014  const rec_t* rec;
2015  const byte* field;
2016  ulint len;
2017  ulint i;
2018  mtr_t mtr;
2019 
2020  ut_ad(mutex_own(&(dict_sys->mutex)));
2021 
2022  foreign->foreign_col_names = static_cast<const char **>(mem_heap_alloc(
2023  foreign->heap, foreign->n_fields * sizeof(void*)));
2024 
2025  foreign->referenced_col_names = static_cast<const char **>(mem_heap_alloc(
2026  foreign->heap, foreign->n_fields * sizeof(void*)));
2027  mtr_start(&mtr);
2028 
2029  sys_foreign_cols = dict_table_get_low("SYS_FOREIGN_COLS");
2030  sys_index = UT_LIST_GET_FIRST(sys_foreign_cols->indexes);
2031  ut_a(!dict_table_is_comp(sys_foreign_cols));
2032 
2033  tuple = dtuple_create(foreign->heap, 1);
2034  dfield = dtuple_get_nth_field(tuple, 0);
2035 
2036  dfield_set_data(dfield, id, ut_strlen(id));
2037  dict_index_copy_types(tuple, sys_index, 1);
2038 
2039  btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
2040  BTR_SEARCH_LEAF, &pcur, &mtr);
2041  for (i = 0; i < foreign->n_fields; i++) {
2042 
2043  rec = btr_pcur_get_rec(&pcur);
2044 
2045  ut_a(btr_pcur_is_on_user_rec(&pcur));
2046  ut_a(!rec_get_deleted_flag(rec, 0));
2047 
2048  field = rec_get_nth_field_old(rec, 0, &len);
2049  ut_a(len == ut_strlen(id));
2050  ut_a(ut_memcmp(id, field, len) == 0);
2051 
2052  field = rec_get_nth_field_old(rec, 1, &len);
2053  ut_a(len == 4);
2054  ut_a(i == mach_read_from_4(field));
2055 
2056  field = rec_get_nth_field_old(rec, 4, &len);
2057  foreign->foreign_col_names[i] = mem_heap_strdupl(
2058  foreign->heap, (char*) field, len);
2059 
2060  field = rec_get_nth_field_old(rec, 5, &len);
2061  foreign->referenced_col_names[i] = mem_heap_strdupl(
2062  foreign->heap, (char*) field, len);
2063 
2064  btr_pcur_move_to_next_user_rec(&pcur, &mtr);
2065  }
2066 
2067  btr_pcur_close(&pcur);
2068  mtr_commit(&mtr);
2069 }
2070 
2071 /***********************************************************************/
2074 static
2075 ulint
2076 dict_load_foreign(
2077 /*==============*/
2078  const char* id,
2080  ibool check_charsets,
2082  ibool check_recursive)
2086 {
2087  dict_foreign_t* foreign;
2088  dict_table_t* sys_foreign;
2089  btr_pcur_t pcur;
2090  dict_index_t* sys_index;
2091  dtuple_t* tuple;
2092  mem_heap_t* heap2;
2093  dfield_t* dfield;
2094  const rec_t* rec;
2095  const byte* field;
2096  ulint len;
2097  ulint n_fields_and_type;
2098  mtr_t mtr;
2099  dict_table_t* for_table;
2100  dict_table_t* ref_table;
2101 
2102  ut_ad(mutex_own(&(dict_sys->mutex)));
2103 
2104  heap2 = mem_heap_create(1000);
2105 
2106  mtr_start(&mtr);
2107 
2108  sys_foreign = dict_table_get_low("SYS_FOREIGN");
2109  sys_index = UT_LIST_GET_FIRST(sys_foreign->indexes);
2110  ut_a(!dict_table_is_comp(sys_foreign));
2111 
2112  tuple = dtuple_create(heap2, 1);
2113  dfield = dtuple_get_nth_field(tuple, 0);
2114 
2115  dfield_set_data(dfield, id, ut_strlen(id));
2116  dict_index_copy_types(tuple, sys_index, 1);
2117 
2118  btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
2119  BTR_SEARCH_LEAF, &pcur, &mtr);
2120  rec = btr_pcur_get_rec(&pcur);
2121 
2122  if (!btr_pcur_is_on_user_rec(&pcur)
2123  || rec_get_deleted_flag(rec, 0)) {
2124  /* Not found */
2125 
2126  fprintf(stderr,
2127  "InnoDB: Error A: cannot load foreign constraint %s\n",
2128  id);
2129 
2130  btr_pcur_close(&pcur);
2131  mtr_commit(&mtr);
2132  mem_heap_free(heap2);
2133 
2134  return(DB_ERROR);
2135  }
2136 
2137  field = rec_get_nth_field_old(rec, 0, &len);
2138 
2139  /* Check if the id in record is the searched one */
2140  if (len != ut_strlen(id) || ut_memcmp(id, field, len) != 0) {
2141 
2142  fprintf(stderr,
2143  "InnoDB: Error B: cannot load foreign constraint %s\n",
2144  id);
2145 
2146  btr_pcur_close(&pcur);
2147  mtr_commit(&mtr);
2148  mem_heap_free(heap2);
2149 
2150  return(DB_ERROR);
2151  }
2152 
2153  /* Read the table names and the number of columns associated
2154  with the constraint */
2155 
2156  mem_heap_free(heap2);
2157 
2158  foreign = dict_mem_foreign_create();
2159 
2160  n_fields_and_type = mach_read_from_4(
2161  rec_get_nth_field_old(rec, 5, &len));
2162 
2163  ut_a(len == 4);
2164 
2165  /* We store the type in the bits 24..29 of n_fields_and_type. */
2166 
2167  foreign->type = (unsigned int) (n_fields_and_type >> 24);
2168  foreign->n_fields = (unsigned int) (n_fields_and_type & 0x3FFUL);
2169 
2170  foreign->id = mem_heap_strdup(foreign->heap, id);
2171 
2172  field = rec_get_nth_field_old(rec, 3, &len);
2173 
2175  foreign->heap, (char*) field, len);
2177 
2178  field = rec_get_nth_field_old(rec, 4, &len);
2180  foreign->heap, (char*) field, len);
2182 
2183  btr_pcur_close(&pcur);
2184  mtr_commit(&mtr);
2185 
2186  dict_load_foreign_cols(id, foreign);
2187 
2189  foreign->referenced_table_name_lookup);
2190 
2191  /* We could possibly wind up in a deep recursive calls if
2192  we call dict_table_get_low() again here if there
2193  is a chain of tables concatenated together with
2194  foreign constraints. In such case, each table is
2195  both a parent and child of the other tables, and
2196  act as a "link" in such table chains.
2197  To avoid such scenario, we would need to check the
2198  number of ancesters the current table has. If that
2199  exceeds DICT_FK_MAX_CHAIN_LEN, we will stop loading
2200  the child table.
2201  Foreign constraints are loaded in a Breath First fashion,
2202  that is, the index on FOR_NAME is scanned first, and then
2203  index on REF_NAME. So foreign constrains in which
2204  current table is a child (foreign table) are loaded first,
2205  and then those constraints where current table is a
2206  parent (referenced) table.
2207  Thus we could check the parent (ref_table) table's
2208  reference count (fk_max_recusive_level) to know how deep the
2209  recursive call is. If the parent table (ref_table) is already
2210  loaded, and its fk_max_recusive_level is larger than
2211  DICT_FK_MAX_CHAIN_LEN, we will stop the recursive loading
2212  by skipping loading the child table. It will not affect foreign
2213  constraint check for DMLs since child table will be loaded
2214  at that time for the constraint check. */
2215  if (!ref_table
2217 
2218  /* If the foreign table is not yet in the dictionary cache, we
2219  have to load it so that we are able to make type comparisons
2220  in the next function call. */
2221 
2222  for_table = dict_table_get_low(foreign->foreign_table_name_lookup);
2223 
2224  if (for_table && ref_table && check_recursive) {
2225  /* This is to record the longest chain of ancesters
2226  this table has, if the parent has more ancesters
2227  than this table has, record it after add 1 (for this
2228  parent */
2229  if (ref_table->fk_max_recusive_level
2230  >= for_table->fk_max_recusive_level) {
2231  for_table->fk_max_recusive_level =
2232  ref_table->fk_max_recusive_level + 1;
2233  }
2234  }
2235  }
2236 
2237  /* Note that there may already be a foreign constraint object in
2238  the dictionary cache for this constraint: then the following
2239  call only sets the pointers in it to point to the appropriate table
2240  and index objects and frees the newly created object foreign.
2241  Adding to the cache should always succeed since we are not creating
2242  a new foreign key constraint but loading one from the data
2243  dictionary. */
2244 
2245  return(dict_foreign_add_to_cache(foreign, check_charsets));
2246 }
2247 
2248 /***********************************************************************/
2255 UNIV_INTERN
2256 ulint
2258 /*===============*/
2259  const char* table_name,
2260  ibool check_recursive,
2262  ibool check_charsets)
2264 {
2265  btr_pcur_t pcur;
2266  mem_heap_t* heap;
2267  dtuple_t* tuple;
2268  dfield_t* dfield;
2269  dict_index_t* sec_index;
2270  dict_table_t* sys_foreign;
2271  const rec_t* rec;
2272  const byte* field;
2273  ulint len;
2274  char* id ;
2275  ulint err;
2276  mtr_t mtr;
2277 
2278  ut_ad(mutex_own(&(dict_sys->mutex)));
2279 
2280  sys_foreign = dict_table_get_low("SYS_FOREIGN");
2281 
2282  if (sys_foreign == NULL) {
2283  /* No foreign keys defined yet in this database */
2284 
2285  fprintf(stderr,
2286  "InnoDB: Error: no foreign key system tables"
2287  " in the database\n");
2288 
2289  return(DB_ERROR);
2290  }
2291 
2292  ut_a(!dict_table_is_comp(sys_foreign));
2293  mtr_start(&mtr);
2294 
2295  /* Get the secondary index based on FOR_NAME from table
2296  SYS_FOREIGN */
2297 
2298  sec_index = dict_table_get_next_index(
2299  dict_table_get_first_index(sys_foreign));
2300 start_load:
2301  heap = mem_heap_create(256);
2302 
2303  tuple = dtuple_create(heap, 1);
2304  dfield = dtuple_get_nth_field(tuple, 0);
2305 
2306  dfield_set_data(dfield, table_name, ut_strlen(table_name));
2307  dict_index_copy_types(tuple, sec_index, 1);
2308 
2309  btr_pcur_open_on_user_rec(sec_index, tuple, PAGE_CUR_GE,
2310  BTR_SEARCH_LEAF, &pcur, &mtr);
2311 loop:
2312  rec = btr_pcur_get_rec(&pcur);
2313 
2314  if (!btr_pcur_is_on_user_rec(&pcur)) {
2315  /* End of index */
2316 
2317  goto load_next_index;
2318  }
2319 
2320  /* Now we have the record in the secondary index containing a table
2321  name and a foreign constraint ID */
2322 
2323  rec = btr_pcur_get_rec(&pcur);
2324  field = rec_get_nth_field_old(rec, 0, &len);
2325 
2326  /* Check if the table name in the record is the one searched for; the
2327  following call does the comparison in the latin1_swedish_ci
2328  charset-collation, in a case-insensitive way. */
2329 
2330  if (0 != cmp_data_data(dfield_get_type(dfield)->mtype,
2331  dfield_get_type(dfield)->prtype,
2332  static_cast<const unsigned char *>(dfield_get_data(dfield)),
2333  dfield_get_len(dfield),
2334  field, len)) {
2335 
2336  goto load_next_index;
2337  }
2338 
2339  /* Since table names in SYS_FOREIGN are stored in a case-insensitive
2340  order, we have to check that the table name matches also in a binary
2341  string comparison. On Unix, MySQL allows table names that only differ
2342  in character case. If lower_case_table_names=2 then what is stored
2343  may not be the same case, but the previous comparison showed that they
2344  match with no-case. */
2345 
2346  if ((srv_lower_case_table_names != 2)
2347  && (0 != ut_memcmp(field, table_name, len))) {
2348  goto next_rec;
2349  }
2350 
2351  if (rec_get_deleted_flag(rec, 0)) {
2352 
2353  goto next_rec;
2354  }
2355 
2356  /* Now we get a foreign key constraint id */
2357  field = rec_get_nth_field_old(rec, 1, &len);
2358  id = mem_heap_strdupl(heap, (char*) field, len);
2359 
2360  btr_pcur_store_position(&pcur, &mtr);
2361 
2362  mtr_commit(&mtr);
2363 
2364  /* Load the foreign constraint definition to the dictionary cache */
2365 
2366  err = dict_load_foreign(id, check_charsets, check_recursive);
2367 
2368  if (err != DB_SUCCESS) {
2369  btr_pcur_close(&pcur);
2370  mem_heap_free(heap);
2371 
2372  return(err);
2373  }
2374 
2375  mtr_start(&mtr);
2376 
2377  btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
2378 next_rec:
2379  btr_pcur_move_to_next_user_rec(&pcur, &mtr);
2380 
2381  goto loop;
2382 
2383 load_next_index:
2384  btr_pcur_close(&pcur);
2385  mtr_commit(&mtr);
2386  mem_heap_free(heap);
2387 
2388  sec_index = dict_table_get_next_index(sec_index);
2389 
2390  if (sec_index != NULL) {
2391 
2392  mtr_start(&mtr);
2393 
2394  /* Switch to scan index on REF_NAME, fk_max_recusive_level
2395  already been updated when scanning FOR_NAME index, no need to
2396  update again */
2397  check_recursive = FALSE;
2398 
2399  goto start_load;
2400  }
2401 
2402  return(DB_SUCCESS);
2403 }
dict_table_t * sys_tables
Definition: dict0dict.h:1192
UNIV_INTERN ibool dtype_is_string_type(ulint mtype)
Definition: data0type.cc:90
UNIV_INTERN void dict_mem_index_add_field(dict_index_t *index, const char *name, ulint prefix_len)
Definition: dict0mem.cc:356
const char * name
Definition: dict0mem.h:339
UNIV_INTERN void dict_table_add_to_cache(dict_table_t *table, mem_heap_t *heap)
Definition: dict0dict.cc:827
UNIV_INLINE ibool btr_pcur_is_on_user_rec(const btr_pcur_t *cursor)
UNIV_INTERN const char * dict_table_get_col_name(const dict_table_t *table, ulint col_nr)
Definition: dict0dict.cc:374
UNIV_INTERN const char * dict_load_table_low(const char *name, const rec_t *rec, dict_table_t **table)
Definition: dict0load.cc:1558
#define DICT_TF_FORMAT_SHIFT
Definition: dict0mem.h:84
char * foreign_table_name_lookup
Definition: dict0mem.h:436
unsigned n_def
Definition: dict0mem.h:502
UNIV_INTERN const char * dict_process_sys_foreign_rec(mem_heap_t *heap, const rec_t *rec, dict_foreign_t *foreign)
Definition: dict0load.cc:454
char * foreign_table_name
Definition: dict0mem.h:435
UNIV_INTERN const char * dict_load_column_low(dict_table_t *table, mem_heap_t *heap, dict_col_t *column, table_id_t *table_id, const char **col_name, const rec_t *rec)
Definition: dict0load.cc:877
UNIV_INTERN dict_table_t * dict_load_table_on_id(table_id_t table_id)
Definition: dict0load.cc:1890
UNIV_INTERN ulint rec_get_nth_field_offs_old(const rec_t *rec, ulint n, ulint *len)
Definition: rem0rec.cc:718
unsigned type
Definition: dict0mem.h:347
UNIV_INLINE void dict_mem_fill_index_struct(dict_index_t *index, mem_heap_t *heap, const char *table_name, const char *index_name, ulint space, ulint type, ulint n_fields)
UNIV_INTERN const char * dict_process_sys_fields_rec(mem_heap_t *heap, const rec_t *rec, dict_field_t *sys_field, ulint *pos, index_id_t *index_id, index_id_t last_id)
Definition: dict0load.cc:419
UNIV_INLINE dtuple_t * dtuple_create(mem_heap_t *heap, ulint n_fields)
UNIV_INTERN const char * dict_process_sys_foreign_col_rec(mem_heap_t *heap, const rec_t *rec, const char **name, const char **for_col_name, const char **ref_col_name, ulint *pos)
Definition: dict0load.cc:529
UNIV_INLINE ulint rec_get_n_fields_old(const rec_t *rec)
UNIV_INTERN void dict_load_sys_table(dict_table_t *table)
Definition: dict0load.cc:1984
UNIV_INTERN void ut_print_filename(FILE *f, const char *name)
Definition: ut0ut.cc:499
#define mem_free(PTR)
Definition: mem0mem.h:249
UNIV_INTERN dict_table_t * dict_load_table(const char *name, ibool cached, dict_err_ignore_t ignore_err)
Definition: dict0load.cc:1710
char * referenced_table_name_lookup
Definition: dict0mem.h:442
UNIV_INTERN const char * dict_load_field_low(byte *index_id, dict_index_t *index, dict_field_t *sys_field, ulint *pos, byte *last_index_id, mem_heap_t *heap, const rec_t *rec)
Definition: dict0load.cc:1081
UNIV_INTERN ibool fil_open_single_table_tablespace(ibool check_space_id, ulint id, ulint flags, const char *name)
Definition: fil0fil.cc:3047
UNIV_INLINE ibool dict_table_is_comp(const dict_table_t *table)
UNIV_INTERN void dict_table_print_low(dict_table_t *table)
Definition: dict0dict.cc:4439
UNIV_INLINE void mach_write_to_8(byte *b, ib_uint64_t n)
mem_heap_t * heap
Definition: dict0mem.h:423
UNIV_INTERN dict_index_t * dict_mem_index_create(const char *table_name, const char *index_name, ulint space, ulint type, ulint n_fields)
Definition: dict0mem.cc:251
#define DICT_TF_FORMAT_51
Definition: dict0mem.h:87
unsigned space
Definition: dict0mem.h:486
#define DICT_TF_FORMAT_ZIP
Definition: dict0mem.h:88
#define mem_heap_free(heap)
Definition: mem0mem.h:117
#define DICT_TF_BITS
Definition: dict0mem.h:100
#define DICT_TF_ZSSIZE_SHIFT
Definition: dict0mem.h:77
UNIV_INTERN void dict_update_statistics(dict_table_t *table, ibool only_calc_if_missing_stats)
Definition: dict0dict.cc:4268
unsigned page
Definition: dict0mem.h:345
UNIV_INLINE dict_table_t * dict_table_get_low(const char *table_name)
UNIV_INTERN void dict_index_copy_types(dtuple_t *tuple, const dict_index_t *index, ulint n_fields)
Definition: dict0dict.cc:1932
char * referenced_table_name
Definition: dict0mem.h:441
UNIV_INTERN dict_hdr_t * dict_hdr_get(mtr_t *mtr)
Definition: dict0boot.cc:48
#define DICT_UNIQUE
Definition: dict0mem.h:52
unsigned corrupted
Definition: dict0mem.h:504
UNIV_INTERN void dict_check_tablespaces_and_store_max_id(ibool in_crash_recovery)
Definition: dict0load.cc:734
UNIV_INLINE void btr_pcur_close(btr_pcur_t *cursor)
UNIV_INTERN char * mem_heap_strdup(mem_heap_t *heap, const char *str)
Definition: mem0mem.cc:107
UNIV_INLINE ulint rec_get_deleted_flag(const rec_t *rec, ulint comp)
UNIV_INTERN char * dict_get_first_table_name_in_db(const char *name)
Definition: dict0load.cc:84
UNIV_INTERN void dict_mem_fill_column_struct(dict_col_t *column, ulint col_pos, ulint mtype, ulint prtype, ulint col_len)
Definition: dict0mem.cc:221
UNIV_INTERN void mtr_commit(mtr_t *mtr) __attribute__((nonnull))
Definition: mtr0mtr.cc:247
UNIV_INLINE void dfield_set_data(dfield_t *field, const void *data, ulint len)
const char ** referenced_col_names
Definition: dict0mem.h:446
UNIV_INTERN ulint mtr_read_ulint(const byte *ptr, ulint type, mtr_t *mtr)
Definition: mtr0mtr.cc:362
UNIV_INLINE ulint dfield_get_len(const dfield_t *field)
#define DICT_CLUSTERED
Definition: dict0mem.h:51
UNIV_INTERN const char * dict_load_index_low(byte *table_id, const char *table_name, mem_heap_t *heap, const rec_t *rec, ibool allocate, dict_index_t **index)
Definition: dict0load.cc:1279
UNIV_INLINE int cmp_data_data(ulint mtype, ulint prtype, const byte *data1, ulint len1, const byte *data2, ulint len2)
unsigned prefix_len
Definition: dict0mem.h:322
UNIV_INTERN dict_table_t * dict_mem_table_create(const char *name, ulint space, ulint n_cols, ulint flags)
Definition: dict0mem.cc:59
table_id_t id
Definition: dict0mem.h:477
UNIV_INLINE char * mem_heap_strdupl(mem_heap_t *heap, const char *str, ulint len)
UNIV_INLINE ulint dict_col_get_no(const dict_col_t *col)
UNIV_INLINE ulint dict_index_is_clust(const dict_index_t *index) __attribute__((pure))
const char * name
Definition: dict0mem.h:321
#define DICT_FK_MAX_RECURSIVE_LOAD
Definition: dict0mem.h:130
UNIV_INTERN const rec_t * dict_startscan_system(btr_pcur_t *pcur, mtr_t *mtr, dict_system_id_t system_id)
Definition: dict0load.cc:260
UNIV_INTERN void btr_pcur_store_position(btr_pcur_t *cursor, mtr_t *mtr)
Definition: btr0pcur.cc:89
unsigned fk_max_recusive_level
Definition: dict0mem.h:533
#define ut_a(EXPR)
Definition: ut0dbg.h:105
UNIV_INTERN void dict_table_add_system_columns(dict_table_t *table, mem_heap_t *heap)
Definition: dict0dict.cc:780
UNIV_INTERN void ut_print_name(FILE *f, struct trx_struct *trx, ibool table_id, const char *name)
Definition: ut0ut.cc:528
UNIV_INLINE const dict_col_t * dict_field_get_col(const dict_field_t *field)
UNIV_INLINE void * mem_heap_alloc(mem_heap_t *heap, ulint n)
#define mem_heap_create(N)
Definition: mem0mem.h:97
unsigned corrupted
Definition: dict0mem.h:369
UNIV_INTERN void fil_set_max_space_id_if_bigger(ulint max_id)
Definition: fil0fil.cc:1696
UNIV_INTERN void dict_mem_table_add_col(dict_table_t *table, mem_heap_t *heap, const char *name, ulint mtype, ulint prtype, ulint len)
Definition: dict0mem.cc:178
#define DICT_TF2_BITS
Definition: dict0mem.h:119
UNIV_INLINE dict_table_t * dict_table_check_if_in_cache_low(const char *table_name)
#define DICT_TF2_SHIFT
Additional table flags.
Definition: dict0mem.h:113
#define UT_LIST_GET_FIRST(BASE)
Definition: ut0lst.h:224
UNIV_INTERN ulint dict_index_add_to_cache(dict_table_t *table, dict_index_t *index, ulint page_no, ibool strict)
Definition: dict0dict.cc:1567
UNIV_INTERN void dict_mem_foreign_table_name_lookup_set(dict_foreign_t *foreign, ibool do_alloc)
Definition: dict0mem.cc:303
#define MLOG_4BYTES
Definition: mtr0mtr.h:75
UNIV_INLINE void mem_heap_empty(mem_heap_t *heap)
dict_sys_t * dict_sys
Definition: dict0dict.cc:63
UNIV_INTERN void dict_mem_index_free(dict_index_t *index)
Definition: dict0mem.cc:381
index_id_t id
Definition: dict0mem.h:337
#define ut_ad(EXPR)
Definition: ut0dbg.h:127
#define DICT_TF_COMPACT
Definition: dict0mem.h:69
unsigned ibd_file_missing
Definition: dict0mem.h:490
#define ut_error
Definition: ut0dbg.h:115
UNIV_INLINE char * mem_strdupl(const char *str, ulint len)
unsigned flags
Definition: dict0mem.h:489
#define FIL_NULL
Definition: fil0fil.h:48
unsigned n_fields
Definition: dict0mem.h:361
UNIV_INLINE ulint dtype_get_charset_coll(ulint prtype)
UNIV_INTERN const rec_t * dict_getnext_system(btr_pcur_t *pcur, mtr_t *mtr)
Definition: dict0load.cc:290
UNIV_INLINE ulint mach_read_from_4(const byte *b) __attribute__((nonnull
UNIV_INTERN dict_foreign_t * dict_mem_foreign_create(void)
Definition: dict0mem.cc:281
#define DICT_TABLE_ORDINARY
Definition: dict0mem.h:60
UNIV_INTERN void ut_print_timestamp(FILE *file)
Definition: ut0ut.cc:247
UNIV_INTERN void dict_print(void)
Definition: dict0load.cc:166
UNIV_INLINE void mtr_start(mtr_t *mtr) __attribute__((nonnull))
UNIV_INLINE ibool btr_pcur_move_to_next_user_rec(btr_pcur_t *cursor, mtr_t *mtr)
unsigned n_fields
Definition: dict0mem.h:427
unsigned n_def
Definition: dict0mem.h:360
UNIV_INTERN void dict_mem_referenced_table_name_lookup_set(dict_foreign_t *foreign, ibool do_alloc)
Definition: dict0mem.cc:330
UNIV_INTERN const char * dict_process_sys_columns_rec(mem_heap_t *heap, const rec_t *rec, dict_col_t *column, table_id_t *table_id, const char **col_name)
Definition: dict0load.cc:397
UNIV_INTERN const char * dict_process_sys_tables_rec(mem_heap_t *heap, const rec_t *rec, dict_table_t **table, dict_table_info_t status)
Definition: dict0load.cc:313
unsigned n_cols
Definition: dict0mem.h:503
UNIV_INTERN ibool fil_space_for_table_exists_in_mem(ulint id, const char *name, ibool is_temp, ibool mark_space, ibool print_error_if_does_not_exist)
Definition: fil0fil.cc:3709
UNIV_INLINE void btr_pcur_open_at_index_side(ibool from_left, dict_index_t *index, ulint latch_mode, btr_pcur_t *pcur, ibool do_init, mtr_t *mtr)
UNIV_INLINE int ut_memcmp(const void *str1, const void *str2, ulint n)
UNIV_INTERN ulint dtype_form_prtype(ulint old_prtype, ulint charset_coll)
Definition: data0type.cc:154
UNIV_INLINE ib_uint64_t mach_read_from_8(const byte *b) __attribute__((nonnull
const char ** foreign_col_names
Definition: dict0mem.h:439
UNIV_INTERN const char * dict_process_sys_indexes_rec(mem_heap_t *heap, const rec_t *rec, dict_index_t *index, table_id_t *table_id)
Definition: dict0load.cc:371
#define DICT_TF2_TEMPORARY
Definition: dict0mem.h:116
UNIV_INTERN ibool dtype_is_binary_string_type(ulint mtype, ulint prtype)
Definition: data0type.cc:111
UNIV_INTERN ulint dict_foreign_add_to_cache(dict_foreign_t *foreign, ibool check_charsets)
Definition: dict0dict.cc:2598
UNIV_INTERN ulint dict_load_foreigns(const char *table_name, ibool check_recursive, ibool check_charsets)
Definition: dict0load.cc:2257
UNIV_INLINE ulint ut_strlen(const char *str)
UNIV_INTERN void dict_table_remove_from_cache(dict_table_t *table)
Definition: dict0dict.cc:1216