~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/dict/dict0load.c

  • Committer: Andy Lester
  • Date: 2008-08-10 01:24:02 UTC
  • mto: (266.1.31 use-replace-funcs)
  • mto: This revision was merged to the branch mainline in revision 295.
  • Revision ID: andy@petdance.com-20080810012402-poten4vrxv1y7rki
make things more const-correct

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************
 
2
Loads to the memory cache database object definitions
 
3
from dictionary tables
 
4
 
 
5
(c) 1996 Innobase Oy
 
6
 
 
7
Created 4/24/1996 Heikki Tuuri
 
8
*******************************************************/
 
9
 
 
10
#include "dict0load.h"
 
11
 
 
12
#ifdef UNIV_NONINL
 
13
#include "dict0load.ic"
 
14
#endif
 
15
 
 
16
#include "btr0pcur.h"
 
17
#include "btr0btr.h"
 
18
#include "page0page.h"
 
19
#include "mach0data.h"
 
20
#include "dict0dict.h"
 
21
#include "dict0boot.h"
 
22
#include "rem0cmp.h"
 
23
#include "srv0start.h"
 
24
#include "srv0srv.h"
 
25
 
 
26
/********************************************************************
 
27
Returns TRUE if index's i'th column's name is 'name' .*/
 
28
static
 
29
ibool
 
30
name_of_col_is(
 
31
/*===========*/
 
32
                                /* out: */
 
33
        dict_table_t*   table,  /* in: table */
 
34
        dict_index_t*   index,  /* in: index */
 
35
        ulint           i,      /* in:  */
 
36
        const char*     name)   /* in: name to compare to */
 
37
{
 
38
        ulint   tmp = dict_col_get_no(dict_field_get_col(
 
39
                                              dict_index_get_nth_field(
 
40
                                                      index, i)));
 
41
 
 
42
        return(strcmp(name, dict_table_get_col_name(table, tmp)) == 0);
 
43
}
 
44
 
 
45
/************************************************************************
 
46
Finds the first table name in the given database. */
 
47
 
 
48
char*
 
49
dict_get_first_table_name_in_db(
 
50
/*============================*/
 
51
                                /* out, own: table name, NULL if
 
52
                                does not exist; the caller must
 
53
                                free the memory in the string! */
 
54
        const char*     name)   /* in: database name which ends in '/' */
 
55
{
 
56
        dict_table_t*   sys_tables;
 
57
        btr_pcur_t      pcur;
 
58
        dict_index_t*   sys_index;
 
59
        dtuple_t*       tuple;
 
60
        mem_heap_t*     heap;
 
61
        dfield_t*       dfield;
 
62
        rec_t*          rec;
 
63
        byte*           field;
 
64
        ulint           len;
 
65
        mtr_t           mtr;
 
66
 
 
67
        ut_ad(mutex_own(&(dict_sys->mutex)));
 
68
 
 
69
        heap = mem_heap_create(1000);
 
70
 
 
71
        mtr_start(&mtr);
 
72
 
 
73
        sys_tables = dict_table_get_low("SYS_TABLES");
 
74
        sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
 
75
        ut_a(!dict_table_is_comp(sys_tables));
 
76
 
 
77
        tuple = dtuple_create(heap, 1);
 
78
        dfield = dtuple_get_nth_field(tuple, 0);
 
79
 
 
80
        dfield_set_data(dfield, name, ut_strlen(name));
 
81
        dict_index_copy_types(tuple, sys_index, 1);
 
82
 
 
83
        btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
 
84
                                  BTR_SEARCH_LEAF, &pcur, &mtr);
 
85
loop:
 
86
        rec = btr_pcur_get_rec(&pcur);
 
87
 
 
88
        if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
 
89
                /* Not found */
 
90
 
 
91
                btr_pcur_close(&pcur);
 
92
                mtr_commit(&mtr);
 
93
                mem_heap_free(heap);
 
94
 
 
95
                return(NULL);
 
96
        }
 
97
 
 
98
        field = rec_get_nth_field_old(rec, 0, &len);
 
99
 
 
100
        if (len < strlen(name)
 
101
            || ut_memcmp(name, field, strlen(name)) != 0) {
 
102
                /* Not found */
 
103
 
 
104
                btr_pcur_close(&pcur);
 
105
                mtr_commit(&mtr);
 
106
                mem_heap_free(heap);
 
107
 
 
108
                return(NULL);
 
109
        }
 
110
 
 
111
        if (!rec_get_deleted_flag(rec, 0)) {
 
112
 
 
113
                /* We found one */
 
114
 
 
115
                char*   table_name = mem_strdupl((char*) field, len);
 
116
 
 
117
                btr_pcur_close(&pcur);
 
118
                mtr_commit(&mtr);
 
119
                mem_heap_free(heap);
 
120
 
 
121
                return(table_name);
 
122
        }
 
123
 
 
124
        btr_pcur_move_to_next_user_rec(&pcur, &mtr);
 
125
 
 
126
        goto loop;
 
127
}
 
128
 
 
129
/************************************************************************
 
130
Prints to the standard output information on all tables found in the data
 
131
dictionary system table. */
 
132
 
 
133
void
 
134
dict_print(void)
 
135
/*============*/
 
136
{
 
137
        dict_table_t*   sys_tables;
 
138
        dict_index_t*   sys_index;
 
139
        dict_table_t*   table;
 
140
        btr_pcur_t      pcur;
 
141
        rec_t*          rec;
 
142
        byte*           field;
 
143
        ulint           len;
 
144
        mtr_t           mtr;
 
145
 
 
146
        /* Enlarge the fatal semaphore wait timeout during the InnoDB table
 
147
        monitor printout */
 
148
 
 
149
        mutex_enter(&kernel_mutex);
 
150
        srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
 
151
        mutex_exit(&kernel_mutex);
 
152
 
 
153
        mutex_enter(&(dict_sys->mutex));
 
154
 
 
155
        mtr_start(&mtr);
 
156
 
 
157
        sys_tables = dict_table_get_low("SYS_TABLES");
 
158
        sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
 
159
 
 
160
        btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
 
161
                                    TRUE, &mtr);
 
162
loop:
 
163
        btr_pcur_move_to_next_user_rec(&pcur, &mtr);
 
164
 
 
165
        rec = btr_pcur_get_rec(&pcur);
 
166
 
 
167
        if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
 
168
                /* end of index */
 
169
 
 
170
                btr_pcur_close(&pcur);
 
171
                mtr_commit(&mtr);
 
172
 
 
173
                mutex_exit(&(dict_sys->mutex));
 
174
 
 
175
                /* Restore the fatal semaphore wait timeout */
 
176
 
 
177
                mutex_enter(&kernel_mutex);
 
178
                srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
 
179
                mutex_exit(&kernel_mutex);
 
180
 
 
181
                return;
 
182
        }
 
183
 
 
184
        field = rec_get_nth_field_old(rec, 0, &len);
 
185
 
 
186
        if (!rec_get_deleted_flag(rec, 0)) {
 
187
 
 
188
                /* We found one */
 
189
 
 
190
                char*   table_name = mem_strdupl((char*) field, len);
 
191
 
 
192
                btr_pcur_store_position(&pcur, &mtr);
 
193
 
 
194
                mtr_commit(&mtr);
 
195
 
 
196
                table = dict_table_get_low(table_name);
 
197
                mem_free(table_name);
 
198
 
 
199
                if (table == NULL) {
 
200
                        fputs("InnoDB: Failed to load table ", stderr);
 
201
                        ut_print_namel(stderr, NULL, TRUE, (char*) field, len);
 
202
                        putc('\n', stderr);
 
203
                } else {
 
204
                        /* The table definition was corrupt if there
 
205
                        is no index */
 
206
 
 
207
                        if (dict_table_get_first_index(table)) {
 
208
                                dict_update_statistics_low(table, TRUE);
 
209
                        }
 
210
 
 
211
                        dict_table_print_low(table);
 
212
                }
 
213
 
 
214
                mtr_start(&mtr);
 
215
 
 
216
                btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
 
217
        }
 
218
 
 
219
        goto loop;
 
220
}
 
221
 
 
222
/************************************************************************
 
223
In a crash recovery we already have all the tablespace objects created.
 
224
This function compares the space id information in the InnoDB data dictionary
 
225
to what we already read with fil_load_single_table_tablespaces().
 
226
 
 
227
In a normal startup, we create the tablespace objects for every table in
 
228
InnoDB's data dictionary, if the corresponding .ibd file exists.
 
229
We also scan the biggest space id, and store it to fil_system. */
 
230
 
 
231
void
 
232
dict_check_tablespaces_and_store_max_id(
 
233
/*====================================*/
 
234
        ibool   in_crash_recovery)      /* in: are we doing a crash recovery */
 
235
{
 
236
        dict_table_t*   sys_tables;
 
237
        dict_index_t*   sys_index;
 
238
        btr_pcur_t      pcur;
 
239
        rec_t*          rec;
 
240
        byte*           field;
 
241
        ulint           len;
 
242
        ulint           space_id;
 
243
        ulint           max_space_id    = 0;
 
244
        mtr_t           mtr;
 
245
 
 
246
        mutex_enter(&(dict_sys->mutex));
 
247
 
 
248
        mtr_start(&mtr);
 
249
 
 
250
        sys_tables = dict_table_get_low("SYS_TABLES");
 
251
        sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
 
252
        ut_a(!dict_table_is_comp(sys_tables));
 
253
 
 
254
        btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
 
255
                                    TRUE, &mtr);
 
256
loop:
 
257
        btr_pcur_move_to_next_user_rec(&pcur, &mtr);
 
258
 
 
259
        rec = btr_pcur_get_rec(&pcur);
 
260
 
 
261
        if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
 
262
                /* end of index */
 
263
 
 
264
                btr_pcur_close(&pcur);
 
265
                mtr_commit(&mtr);
 
266
 
 
267
                /* We must make the tablespace cache aware of the biggest
 
268
                known space id */
 
269
 
 
270
                /* printf("Biggest space id in data dictionary %lu\n",
 
271
                max_space_id); */
 
272
                fil_set_max_space_id_if_bigger(max_space_id);
 
273
 
 
274
                mutex_exit(&(dict_sys->mutex));
 
275
 
 
276
                return;
 
277
        }
 
278
 
 
279
        field = rec_get_nth_field_old(rec, 0, &len);
 
280
 
 
281
        if (!rec_get_deleted_flag(rec, 0)) {
 
282
 
 
283
                /* We found one */
 
284
 
 
285
                char*   name = mem_strdupl((char*) field, len);
 
286
 
 
287
                field = rec_get_nth_field_old(rec, 9, &len);
 
288
                ut_a(len == 4);
 
289
 
 
290
                space_id = mach_read_from_4(field);
 
291
 
 
292
                btr_pcur_store_position(&pcur, &mtr);
 
293
 
 
294
                mtr_commit(&mtr);
 
295
 
 
296
                if (space_id != 0 && in_crash_recovery) {
 
297
                        /* Check that the tablespace (the .ibd file) really
 
298
                        exists; print a warning to the .err log if not */
 
299
 
 
300
                        fil_space_for_table_exists_in_mem(space_id, name,
 
301
                                                          FALSE, TRUE, TRUE);
 
302
                }
 
303
 
 
304
                if (space_id != 0 && !in_crash_recovery) {
 
305
                        /* It is a normal database startup: create the space
 
306
                        object and check that the .ibd file exists. */
 
307
 
 
308
                        fil_open_single_table_tablespace(FALSE, space_id,
 
309
                                                         name);
 
310
                }
 
311
 
 
312
                mem_free(name);
 
313
 
 
314
                if (space_id > max_space_id) {
 
315
                        max_space_id = space_id;
 
316
                }
 
317
 
 
318
                mtr_start(&mtr);
 
319
 
 
320
                btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
 
321
        }
 
322
 
 
323
        goto loop;
 
324
}
 
325
 
 
326
/************************************************************************
 
327
Loads definitions for table columns. */
 
328
static
 
329
void
 
330
dict_load_columns(
 
331
/*==============*/
 
332
        dict_table_t*   table,  /* in: table */
 
333
        mem_heap_t*     heap)   /* in: memory heap for temporary storage */
 
334
{
 
335
        dict_table_t*   sys_columns;
 
336
        dict_index_t*   sys_index;
 
337
        btr_pcur_t      pcur;
 
338
        dtuple_t*       tuple;
 
339
        dfield_t*       dfield;
 
340
        rec_t*          rec;
 
341
        byte*           field;
 
342
        ulint           len;
 
343
        byte*           buf;
 
344
        char*           name;
 
345
        ulint           mtype;
 
346
        ulint           prtype;
 
347
        ulint           col_len;
 
348
        ulint           i;
 
349
        mtr_t           mtr;
 
350
 
 
351
        ut_ad(mutex_own(&(dict_sys->mutex)));
 
352
 
 
353
        mtr_start(&mtr);
 
354
 
 
355
        sys_columns = dict_table_get_low("SYS_COLUMNS");
 
356
        sys_index = UT_LIST_GET_FIRST(sys_columns->indexes);
 
357
        ut_a(!dict_table_is_comp(sys_columns));
 
358
 
 
359
        tuple = dtuple_create(heap, 1);
 
360
        dfield = dtuple_get_nth_field(tuple, 0);
 
361
 
 
362
        buf = mem_heap_alloc(heap, 8);
 
363
        mach_write_to_8(buf, table->id);
 
364
 
 
365
        dfield_set_data(dfield, buf, 8);
 
366
        dict_index_copy_types(tuple, sys_index, 1);
 
367
 
 
368
        btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
 
369
                                  BTR_SEARCH_LEAF, &pcur, &mtr);
 
370
        for (i = 0; i + DATA_N_SYS_COLS < (ulint) table->n_cols; i++) {
 
371
 
 
372
                rec = btr_pcur_get_rec(&pcur);
 
373
 
 
374
                ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
 
375
 
 
376
                ut_a(!rec_get_deleted_flag(rec, 0));
 
377
 
 
378
                field = rec_get_nth_field_old(rec, 0, &len);
 
379
                ut_ad(len == 8);
 
380
                ut_a(ut_dulint_cmp(table->id, mach_read_from_8(field)) == 0);
 
381
 
 
382
                field = rec_get_nth_field_old(rec, 1, &len);
 
383
                ut_ad(len == 4);
 
384
                ut_a(i == mach_read_from_4(field));
 
385
 
 
386
                ut_a(name_of_col_is(sys_columns, sys_index, 4, "NAME"));
 
387
 
 
388
                field = rec_get_nth_field_old(rec, 4, &len);
 
389
                name = mem_heap_strdupl(heap, (char*) field, len);
 
390
 
 
391
                field = rec_get_nth_field_old(rec, 5, &len);
 
392
                mtype = mach_read_from_4(field);
 
393
 
 
394
                field = rec_get_nth_field_old(rec, 6, &len);
 
395
                prtype = mach_read_from_4(field);
 
396
 
 
397
                if (dtype_get_charset_coll(prtype) == 0
 
398
                    && dtype_is_string_type(mtype)) {
 
399
                        /* The table was created with < 4.1.2. */
 
400
 
 
401
                        if (dtype_is_binary_string_type(mtype, prtype)) {
 
402
                                /* Use the binary collation for
 
403
                                string columns of binary type. */
 
404
 
 
405
                                prtype = dtype_form_prtype(
 
406
                                        prtype,
 
407
                                        DATA_MYSQL_BINARY_CHARSET_COLL);
 
408
                        } else {
 
409
                                /* Use the default charset for
 
410
                                other than binary columns. */
 
411
 
 
412
                                prtype = dtype_form_prtype(
 
413
                                        prtype,
 
414
                                        data_mysql_default_charset_coll);
 
415
                        }
 
416
                }
 
417
 
 
418
                field = rec_get_nth_field_old(rec, 7, &len);
 
419
                col_len = mach_read_from_4(field);
 
420
 
 
421
                ut_a(name_of_col_is(sys_columns, sys_index, 8, "PREC"));
 
422
 
 
423
                dict_mem_table_add_col(table, heap, name,
 
424
                                       mtype, prtype, col_len);
 
425
                btr_pcur_move_to_next_user_rec(&pcur, &mtr);
 
426
        }
 
427
 
 
428
        btr_pcur_close(&pcur);
 
429
        mtr_commit(&mtr);
 
430
}
 
431
 
 
432
/************************************************************************
 
433
Report that an index field or index for a table has been delete marked. */
 
434
static
 
435
void
 
436
dict_load_report_deleted_index(
 
437
/*===========================*/
 
438
        const char*     name,   /* in: table name */
 
439
        ulint           field)  /* in: index field, or ULINT_UNDEFINED */
 
440
{
 
441
        fprintf(stderr, "InnoDB: Error: data dictionary entry"
 
442
                " for table %s is corrupt!\n", name);
 
443
        if (field != ULINT_UNDEFINED) {
 
444
                fprintf(stderr,
 
445
                        "InnoDB: Index field %lu is delete marked.\n", field);
 
446
        } else {
 
447
                fputs("InnoDB: An index is delete marked.\n", stderr);
 
448
        }
 
449
}
 
450
 
 
451
/************************************************************************
 
452
Loads definitions for index fields. */
 
453
static
 
454
void
 
455
dict_load_fields(
 
456
/*=============*/
 
457
        dict_table_t*   table,  /* in: table */
 
458
        dict_index_t*   index,  /* in: index whose fields to load */
 
459
        mem_heap_t*     heap)   /* in: memory heap for temporary storage */
 
460
{
 
461
        dict_table_t*   sys_fields;
 
462
        dict_index_t*   sys_index;
 
463
        btr_pcur_t      pcur;
 
464
        dtuple_t*       tuple;
 
465
        dfield_t*       dfield;
 
466
        ulint           pos_and_prefix_len;
 
467
        ulint           prefix_len;
 
468
        rec_t*          rec;
 
469
        byte*           field;
 
470
        ulint           len;
 
471
        byte*           buf;
 
472
        ulint           i;
 
473
        mtr_t           mtr;
 
474
 
 
475
        ut_ad(mutex_own(&(dict_sys->mutex)));
 
476
 
 
477
        mtr_start(&mtr);
 
478
 
 
479
        sys_fields = dict_table_get_low("SYS_FIELDS");
 
480
        sys_index = UT_LIST_GET_FIRST(sys_fields->indexes);
 
481
        ut_a(!dict_table_is_comp(sys_fields));
 
482
 
 
483
        tuple = dtuple_create(heap, 1);
 
484
        dfield = dtuple_get_nth_field(tuple, 0);
 
485
 
 
486
        buf = mem_heap_alloc(heap, 8);
 
487
        mach_write_to_8(buf, index->id);
 
488
 
 
489
        dfield_set_data(dfield, buf, 8);
 
490
        dict_index_copy_types(tuple, sys_index, 1);
 
491
 
 
492
        btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
 
493
                                  BTR_SEARCH_LEAF, &pcur, &mtr);
 
494
        for (i = 0; i < index->n_fields; i++) {
 
495
 
 
496
                rec = btr_pcur_get_rec(&pcur);
 
497
 
 
498
                ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
 
499
                if (rec_get_deleted_flag(rec, 0)) {
 
500
                        dict_load_report_deleted_index(table->name, i);
 
501
                }
 
502
 
 
503
                field = rec_get_nth_field_old(rec, 0, &len);
 
504
                ut_ad(len == 8);
 
505
                ut_a(ut_memcmp(buf, field, len) == 0);
 
506
 
 
507
                field = rec_get_nth_field_old(rec, 1, &len);
 
508
                ut_a(len == 4);
 
509
 
 
510
                /* The next field stores the field position in the index
 
511
                and a possible column prefix length if the index field
 
512
                does not contain the whole column. The storage format is
 
513
                like this: if there is at least one prefix field in the index,
 
514
                then the HIGH 2 bytes contain the field number (== i) and the
 
515
                low 2 bytes the prefix length for the field. Otherwise the
 
516
                field number (== i) is contained in the 2 LOW bytes. */
 
517
 
 
518
                pos_and_prefix_len = mach_read_from_4(field);
 
519
 
 
520
                ut_a((pos_and_prefix_len & 0xFFFFUL) == i
 
521
                     || (pos_and_prefix_len & 0xFFFF0000UL) == (i << 16));
 
522
 
 
523
                if ((i == 0 && pos_and_prefix_len > 0)
 
524
                    || (pos_and_prefix_len & 0xFFFF0000UL) > 0) {
 
525
 
 
526
                        prefix_len = pos_and_prefix_len & 0xFFFFUL;
 
527
                } else {
 
528
                        prefix_len = 0;
 
529
                }
 
530
 
 
531
                ut_a(name_of_col_is(sys_fields, sys_index, 4, "COL_NAME"));
 
532
 
 
533
                field = rec_get_nth_field_old(rec, 4, &len);
 
534
 
 
535
                dict_mem_index_add_field(index,
 
536
                                         mem_heap_strdupl(heap,
 
537
                                                          (char*) field, len),
 
538
                                         prefix_len);
 
539
 
 
540
                btr_pcur_move_to_next_user_rec(&pcur, &mtr);
 
541
        }
 
542
 
 
543
        btr_pcur_close(&pcur);
 
544
        mtr_commit(&mtr);
 
545
}
 
546
 
 
547
/************************************************************************
 
548
Loads definitions for table indexes. Adds them to the data dictionary
 
549
cache. */
 
550
static
 
551
ulint
 
552
dict_load_indexes(
 
553
/*==============*/
 
554
                                /* out: DB_SUCCESS if ok, DB_CORRUPTION
 
555
                                if corruption of dictionary table or
 
556
                                DB_UNSUPPORTED if table has unknown index
 
557
                                type */
 
558
        dict_table_t*   table,  /* in: table */
 
559
        mem_heap_t*     heap)   /* in: memory heap for temporary storage */
 
560
{
 
561
        dict_table_t*   sys_indexes;
 
562
        dict_index_t*   sys_index;
 
563
        dict_index_t*   index;
 
564
        btr_pcur_t      pcur;
 
565
        dtuple_t*       tuple;
 
566
        dfield_t*       dfield;
 
567
        rec_t*          rec;
 
568
        byte*           field;
 
569
        ulint           len;
 
570
        ulint           name_len;
 
571
        char*           name_buf;
 
572
        ulint           type;
 
573
        ulint           space;
 
574
        ulint           page_no;
 
575
        ulint           n_fields;
 
576
        byte*           buf;
 
577
        ibool           is_sys_table;
 
578
        dulint          id;
 
579
        mtr_t           mtr;
 
580
        ulint           error = DB_SUCCESS;
 
581
 
 
582
        ut_ad(mutex_own(&(dict_sys->mutex)));
 
583
 
 
584
        if ((ut_dulint_get_high(table->id) == 0)
 
585
            && (ut_dulint_get_low(table->id) < DICT_HDR_FIRST_ID)) {
 
586
                is_sys_table = TRUE;
 
587
        } else {
 
588
                is_sys_table = FALSE;
 
589
        }
 
590
 
 
591
        mtr_start(&mtr);
 
592
 
 
593
        sys_indexes = dict_table_get_low("SYS_INDEXES");
 
594
        sys_index = UT_LIST_GET_FIRST(sys_indexes->indexes);
 
595
        ut_a(!dict_table_is_comp(sys_indexes));
 
596
 
 
597
        tuple = dtuple_create(heap, 1);
 
598
        dfield = dtuple_get_nth_field(tuple, 0);
 
599
 
 
600
        buf = mem_heap_alloc(heap, 8);
 
601
        mach_write_to_8(buf, table->id);
 
602
 
 
603
        dfield_set_data(dfield, buf, 8);
 
604
        dict_index_copy_types(tuple, sys_index, 1);
 
605
 
 
606
        btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
 
607
                                  BTR_SEARCH_LEAF, &pcur, &mtr);
 
608
        for (;;) {
 
609
                if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
 
610
 
 
611
                        break;
 
612
                }
 
613
 
 
614
                rec = btr_pcur_get_rec(&pcur);
 
615
 
 
616
                field = rec_get_nth_field_old(rec, 0, &len);
 
617
                ut_ad(len == 8);
 
618
 
 
619
                if (ut_memcmp(buf, field, len) != 0) {
 
620
                        break;
 
621
                }
 
622
 
 
623
                if (rec_get_deleted_flag(rec, 0)) {
 
624
                        dict_load_report_deleted_index(table->name,
 
625
                                                       ULINT_UNDEFINED);
 
626
 
 
627
                        error = DB_CORRUPTION;
 
628
                        goto func_exit;
 
629
                }
 
630
 
 
631
                field = rec_get_nth_field_old(rec, 1, &len);
 
632
                ut_ad(len == 8);
 
633
                id = mach_read_from_8(field);
 
634
 
 
635
                ut_a(name_of_col_is(sys_indexes, sys_index, 4, "NAME"));
 
636
 
 
637
                field = rec_get_nth_field_old(rec, 4, &name_len);
 
638
                name_buf = mem_heap_strdupl(heap, (char*) field, name_len);
 
639
 
 
640
                field = rec_get_nth_field_old(rec, 5, &len);
 
641
                n_fields = mach_read_from_4(field);
 
642
 
 
643
                field = rec_get_nth_field_old(rec, 6, &len);
 
644
                type = mach_read_from_4(field);
 
645
 
 
646
                field = rec_get_nth_field_old(rec, 7, &len);
 
647
                space = mach_read_from_4(field);
 
648
 
 
649
                ut_a(name_of_col_is(sys_indexes, sys_index, 8, "PAGE_NO"));
 
650
 
 
651
                field = rec_get_nth_field_old(rec, 8, &len);
 
652
                page_no = mach_read_from_4(field);
 
653
 
 
654
                /* We check for unsupported types first, so that the
 
655
                subsequent checks are relevant for the supported types. */
 
656
                if (type & ~(DICT_CLUSTERED | DICT_UNIQUE)) {
 
657
 
 
658
                        fprintf(stderr,
 
659
                                "InnoDB: Error: unknown type %lu"
 
660
                                " of index %s of table %s\n",
 
661
                                (ulong) type, name_buf, table->name);
 
662
 
 
663
                        error = DB_UNSUPPORTED;
 
664
                        goto func_exit;
 
665
                } else if (page_no == FIL_NULL) {
 
666
 
 
667
                        fprintf(stderr,
 
668
                                "InnoDB: Error: trying to load index %s"
 
669
                                " for table %s\n"
 
670
                                "InnoDB: but the index tree has been freed!\n",
 
671
                                name_buf, table->name);
 
672
 
 
673
                        error = DB_CORRUPTION;
 
674
                        goto func_exit;
 
675
                } else if ((type & DICT_CLUSTERED) == 0
 
676
                            && NULL == dict_table_get_first_index(table)) {
 
677
 
 
678
                        fprintf(stderr,
 
679
                                "InnoDB: Error: trying to load index %s"
 
680
                                " for table %s\n"
 
681
                                "InnoDB: but the first index"
 
682
                                " is not clustered!\n",
 
683
                                name_buf, table->name);
 
684
 
 
685
                        error = DB_CORRUPTION;
 
686
                        goto func_exit;
 
687
                } else if (is_sys_table
 
688
                           && ((type & DICT_CLUSTERED)
 
689
                               || ((table == dict_sys->sys_tables)
 
690
                                   && (name_len == (sizeof "ID_IND") - 1)
 
691
                                   && (0 == ut_memcmp(name_buf,
 
692
                                                      "ID_IND", name_len))))) {
 
693
 
 
694
                        /* The index was created in memory already at booting
 
695
                        of the database server */
 
696
                } else {
 
697
                        index = dict_mem_index_create(table->name, name_buf,
 
698
                                                      space, type, n_fields);
 
699
                        index->id = id;
 
700
 
 
701
                        dict_load_fields(table, index, heap);
 
702
                        dict_index_add_to_cache(table, index, page_no);
 
703
                }
 
704
 
 
705
                btr_pcur_move_to_next_user_rec(&pcur, &mtr);
 
706
        }
 
707
 
 
708
func_exit:
 
709
        btr_pcur_close(&pcur);
 
710
        mtr_commit(&mtr);
 
711
 
 
712
        return(error);
 
713
}
 
714
 
 
715
/************************************************************************
 
716
Loads a table definition and also all its index definitions, and also
 
717
the cluster definition if the table is a member in a cluster. Also loads
 
718
all foreign key constraints where the foreign key is in the table or where
 
719
a foreign key references columns in this table. Adds all these to the data
 
720
dictionary cache. */
 
721
 
 
722
dict_table_t*
 
723
dict_load_table(
 
724
/*============*/
 
725
                                /* out: table, NULL if does not exist;
 
726
                                if the table is stored in an .ibd file,
 
727
                                but the file does not exist,
 
728
                                then we set the ibd_file_missing flag TRUE
 
729
                                in the table object we return */
 
730
        const char*     name)   /* in: table name in the
 
731
                                databasename/tablename format */
 
732
{
 
733
        ibool           ibd_file_missing        = FALSE;
 
734
        dict_table_t*   table;
 
735
        dict_table_t*   sys_tables;
 
736
        btr_pcur_t      pcur;
 
737
        dict_index_t*   sys_index;
 
738
        dtuple_t*       tuple;
 
739
        mem_heap_t*     heap;
 
740
        dfield_t*       dfield;
 
741
        rec_t*          rec;
 
742
        byte*           field;
 
743
        ulint           len;
 
744
        ulint           space;
 
745
        ulint           n_cols;
 
746
        ulint           flags;
 
747
        ulint           err;
 
748
        mtr_t           mtr;
 
749
 
 
750
        ut_ad(mutex_own(&(dict_sys->mutex)));
 
751
 
 
752
        heap = mem_heap_create(32000);
 
753
 
 
754
        mtr_start(&mtr);
 
755
 
 
756
        sys_tables = dict_table_get_low("SYS_TABLES");
 
757
        sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
 
758
        ut_a(!dict_table_is_comp(sys_tables));
 
759
 
 
760
        tuple = dtuple_create(heap, 1);
 
761
        dfield = dtuple_get_nth_field(tuple, 0);
 
762
 
 
763
        dfield_set_data(dfield, name, ut_strlen(name));
 
764
        dict_index_copy_types(tuple, sys_index, 1);
 
765
 
 
766
        btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
 
767
                                  BTR_SEARCH_LEAF, &pcur, &mtr);
 
768
        rec = btr_pcur_get_rec(&pcur);
 
769
 
 
770
        if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
 
771
            || rec_get_deleted_flag(rec, 0)) {
 
772
                /* Not found */
 
773
err_exit:
 
774
                btr_pcur_close(&pcur);
 
775
                mtr_commit(&mtr);
 
776
                mem_heap_free(heap);
 
777
 
 
778
                return(NULL);
 
779
        }
 
780
 
 
781
        field = rec_get_nth_field_old(rec, 0, &len);
 
782
 
 
783
        /* Check if the table name in record is the searched one */
 
784
        if (len != ut_strlen(name) || ut_memcmp(name, field, len) != 0) {
 
785
 
 
786
                goto err_exit;
 
787
        }
 
788
 
 
789
        ut_a(name_of_col_is(sys_tables, sys_index, 9, "SPACE"));
 
790
 
 
791
        field = rec_get_nth_field_old(rec, 9, &len);
 
792
        space = mach_read_from_4(field);
 
793
 
 
794
        /* Check if the tablespace exists and has the right name */
 
795
        if (space != 0) {
 
796
                if (fil_space_for_table_exists_in_mem(space, name, FALSE,
 
797
                                                      FALSE, FALSE)) {
 
798
                        /* Ok; (if we did a crash recovery then the tablespace
 
799
                        can already be in the memory cache) */
 
800
                } else {
 
801
                        /* In >= 4.1.9, InnoDB scans the data dictionary also
 
802
                        at a normal mysqld startup. It is an error if the
 
803
                        space object does not exist in memory. */
 
804
 
 
805
                        ut_print_timestamp(stderr);
 
806
                        fprintf(stderr,
 
807
                                "  InnoDB: error: space object of table %s,\n"
 
808
                                "InnoDB: space id %lu did not exist in memory."
 
809
                                " Retrying an open.\n",
 
810
                                name, (ulong)space);
 
811
                        /* Try to open the tablespace */
 
812
                        if (!fil_open_single_table_tablespace(TRUE,
 
813
                                                              space, name)) {
 
814
                                /* We failed to find a sensible tablespace
 
815
                                file */
 
816
 
 
817
                                ibd_file_missing = TRUE;
 
818
                        }
 
819
                }
 
820
        }
 
821
 
 
822
        ut_a(name_of_col_is(sys_tables, sys_index, 4, "N_COLS"));
 
823
 
 
824
        field = rec_get_nth_field_old(rec, 4, &len);
 
825
        n_cols = mach_read_from_4(field);
 
826
 
 
827
        flags = 0;
 
828
 
 
829
        /* The high-order bit of N_COLS is the "compact format" flag. */
 
830
        if (n_cols & 0x80000000UL) {
 
831
                flags |= DICT_TF_COMPACT;
 
832
        }
 
833
 
 
834
        table = dict_mem_table_create(name, space, n_cols & ~0x80000000UL,
 
835
                                      flags);
 
836
 
 
837
        table->ibd_file_missing = (unsigned int) ibd_file_missing;
 
838
 
 
839
        ut_a(name_of_col_is(sys_tables, sys_index, 3, "ID"));
 
840
 
 
841
        field = rec_get_nth_field_old(rec, 3, &len);
 
842
        table->id = mach_read_from_8(field);
 
843
 
 
844
        field = rec_get_nth_field_old(rec, 5, &len);
 
845
        if (UNIV_UNLIKELY(mach_read_from_4(field) != DICT_TABLE_ORDINARY)) {
 
846
                ut_print_timestamp(stderr);
 
847
                fprintf(stderr,
 
848
                        "  InnoDB: table %s: unknown table type %lu\n",
 
849
                        name, (ulong) mach_read_from_4(field));
 
850
                goto err_exit;
 
851
        }
 
852
 
 
853
        btr_pcur_close(&pcur);
 
854
        mtr_commit(&mtr);
 
855
 
 
856
        dict_load_columns(table, heap);
 
857
 
 
858
        dict_table_add_to_cache(table, heap);
 
859
 
 
860
        mem_heap_empty(heap);
 
861
 
 
862
        err = dict_load_indexes(table, heap);
 
863
 
 
864
        /* If the force recovery flag is set, we open the table irrespective
 
865
        of the error condition, since the user may want to dump data from the
 
866
        clustered index. However we load the foreign key information only if
 
867
        all indexes were loaded. */
 
868
        if (err != DB_SUCCESS && !srv_force_recovery) {
 
869
                dict_mem_table_free(table);
 
870
                table = NULL;
 
871
        } else if (err == DB_SUCCESS) {
 
872
                err = dict_load_foreigns(table->name, TRUE);
 
873
        }
 
874
#if 0
 
875
        if (err != DB_SUCCESS && table != NULL) {
 
876
 
 
877
                mutex_enter(&dict_foreign_err_mutex);
 
878
 
 
879
                ut_print_timestamp(stderr);
 
880
 
 
881
                fprintf(stderr,
 
882
                        "  InnoDB: Error: could not make a foreign key"
 
883
                        " definition to match\n"
 
884
                        "InnoDB: the foreign key table"
 
885
                        " or the referenced table!\n"
 
886
                        "InnoDB: The data dictionary of InnoDB is corrupt."
 
887
                        " You may need to drop\n"
 
888
                        "InnoDB: and recreate the foreign key table"
 
889
                        " or the referenced table.\n"
 
890
                        "InnoDB: Submit a detailed bug report"
 
891
                        " to http://bugs.mysql.com\n"
 
892
                        "InnoDB: Latest foreign key error printout:\n%s\n",
 
893
                        dict_foreign_err_buf);
 
894
 
 
895
                mutex_exit(&dict_foreign_err_mutex);
 
896
        }
 
897
#endif /* 0 */
 
898
        mem_heap_free(heap);
 
899
 
 
900
        return(table);
 
901
}
 
902
 
 
903
/***************************************************************************
 
904
Loads a table object based on the table id. */
 
905
 
 
906
dict_table_t*
 
907
dict_load_table_on_id(
 
908
/*==================*/
 
909
                                /* out: table; NULL if table does not exist */
 
910
        dulint  table_id)       /* in: table id */
 
911
{
 
912
        byte            id_buf[8];
 
913
        btr_pcur_t      pcur;
 
914
        mem_heap_t*     heap;
 
915
        dtuple_t*       tuple;
 
916
        dfield_t*       dfield;
 
917
        dict_index_t*   sys_table_ids;
 
918
        dict_table_t*   sys_tables;
 
919
        rec_t*          rec;
 
920
        byte*           field;
 
921
        ulint           len;
 
922
        dict_table_t*   table;
 
923
        mtr_t           mtr;
 
924
 
 
925
        ut_ad(mutex_own(&(dict_sys->mutex)));
 
926
 
 
927
        /* NOTE that the operation of this function is protected by
 
928
        the dictionary mutex, and therefore no deadlocks can occur
 
929
        with other dictionary operations. */
 
930
 
 
931
        mtr_start(&mtr);
 
932
        /*---------------------------------------------------*/
 
933
        /* Get the secondary index based on ID for table SYS_TABLES */
 
934
        sys_tables = dict_sys->sys_tables;
 
935
        sys_table_ids = dict_table_get_next_index(
 
936
                dict_table_get_first_index(sys_tables));
 
937
        ut_a(!dict_table_is_comp(sys_tables));
 
938
        heap = mem_heap_create(256);
 
939
 
 
940
        tuple  = dtuple_create(heap, 1);
 
941
        dfield = dtuple_get_nth_field(tuple, 0);
 
942
 
 
943
        /* Write the table id in byte format to id_buf */
 
944
        mach_write_to_8(id_buf, table_id);
 
945
 
 
946
        dfield_set_data(dfield, id_buf, 8);
 
947
        dict_index_copy_types(tuple, sys_table_ids, 1);
 
948
 
 
949
        btr_pcur_open_on_user_rec(sys_table_ids, tuple, PAGE_CUR_GE,
 
950
                                  BTR_SEARCH_LEAF, &pcur, &mtr);
 
951
        rec = btr_pcur_get_rec(&pcur);
 
952
 
 
953
        if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
 
954
            || rec_get_deleted_flag(rec, 0)) {
 
955
                /* Not found */
 
956
 
 
957
                btr_pcur_close(&pcur);
 
958
                mtr_commit(&mtr);
 
959
                mem_heap_free(heap);
 
960
 
 
961
                return(NULL);
 
962
        }
 
963
 
 
964
        /*---------------------------------------------------*/
 
965
        /* Now we have the record in the secondary index containing the
 
966
        table ID and NAME */
 
967
 
 
968
        rec = btr_pcur_get_rec(&pcur);
 
969
        field = rec_get_nth_field_old(rec, 0, &len);
 
970
        ut_ad(len == 8);
 
971
 
 
972
        /* Check if the table id in record is the one searched for */
 
973
        if (ut_dulint_cmp(table_id, mach_read_from_8(field)) != 0) {
 
974
 
 
975
                btr_pcur_close(&pcur);
 
976
                mtr_commit(&mtr);
 
977
                mem_heap_free(heap);
 
978
 
 
979
                return(NULL);
 
980
        }
 
981
 
 
982
        /* Now we get the table name from the record */
 
983
        field = rec_get_nth_field_old(rec, 1, &len);
 
984
        /* Load the table definition to memory */
 
985
        table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len));
 
986
 
 
987
        btr_pcur_close(&pcur);
 
988
        mtr_commit(&mtr);
 
989
        mem_heap_free(heap);
 
990
 
 
991
        return(table);
 
992
}
 
993
 
 
994
/************************************************************************
 
995
This function is called when the database is booted. Loads system table
 
996
index definitions except for the clustered index which is added to the
 
997
dictionary cache at booting before calling this function. */
 
998
 
 
999
void
 
1000
dict_load_sys_table(
 
1001
/*================*/
 
1002
        dict_table_t*   table)  /* in: system table */
 
1003
{
 
1004
        mem_heap_t*     heap;
 
1005
 
 
1006
        ut_ad(mutex_own(&(dict_sys->mutex)));
 
1007
 
 
1008
        heap = mem_heap_create(1000);
 
1009
 
 
1010
        dict_load_indexes(table, heap);
 
1011
 
 
1012
        mem_heap_free(heap);
 
1013
}
 
1014
 
 
1015
/************************************************************************
 
1016
Loads foreign key constraint col names (also for the referenced table). */
 
1017
static
 
1018
void
 
1019
dict_load_foreign_cols(
 
1020
/*===================*/
 
1021
        const char*     id,     /* in: foreign constraint id as a
 
1022
                                null-terminated string */
 
1023
        dict_foreign_t* foreign)/* in: foreign constraint object */
 
1024
{
 
1025
        dict_table_t*   sys_foreign_cols;
 
1026
        dict_index_t*   sys_index;
 
1027
        btr_pcur_t      pcur;
 
1028
        dtuple_t*       tuple;
 
1029
        dfield_t*       dfield;
 
1030
        rec_t*          rec;
 
1031
        byte*           field;
 
1032
        ulint           len;
 
1033
        ulint           i;
 
1034
        mtr_t           mtr;
 
1035
 
 
1036
        ut_ad(mutex_own(&(dict_sys->mutex)));
 
1037
 
 
1038
        foreign->foreign_col_names = mem_heap_alloc(
 
1039
                foreign->heap, foreign->n_fields * sizeof(void*));
 
1040
 
 
1041
        foreign->referenced_col_names = mem_heap_alloc(
 
1042
                foreign->heap, foreign->n_fields * sizeof(void*));
 
1043
        mtr_start(&mtr);
 
1044
 
 
1045
        sys_foreign_cols = dict_table_get_low("SYS_FOREIGN_COLS");
 
1046
        sys_index = UT_LIST_GET_FIRST(sys_foreign_cols->indexes);
 
1047
        ut_a(!dict_table_is_comp(sys_foreign_cols));
 
1048
 
 
1049
        tuple = dtuple_create(foreign->heap, 1);
 
1050
        dfield = dtuple_get_nth_field(tuple, 0);
 
1051
 
 
1052
        dfield_set_data(dfield, id, ut_strlen(id));
 
1053
        dict_index_copy_types(tuple, sys_index, 1);
 
1054
 
 
1055
        btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
 
1056
                                  BTR_SEARCH_LEAF, &pcur, &mtr);
 
1057
        for (i = 0; i < foreign->n_fields; i++) {
 
1058
 
 
1059
                rec = btr_pcur_get_rec(&pcur);
 
1060
 
 
1061
                ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
 
1062
                ut_a(!rec_get_deleted_flag(rec, 0));
 
1063
 
 
1064
                field = rec_get_nth_field_old(rec, 0, &len);
 
1065
                ut_a(len == ut_strlen(id));
 
1066
                ut_a(ut_memcmp(id, field, len) == 0);
 
1067
 
 
1068
                field = rec_get_nth_field_old(rec, 1, &len);
 
1069
                ut_a(len == 4);
 
1070
                ut_a(i == mach_read_from_4(field));
 
1071
 
 
1072
                field = rec_get_nth_field_old(rec, 4, &len);
 
1073
                foreign->foreign_col_names[i] = mem_heap_strdupl(
 
1074
                        foreign->heap, (char*) field, len);
 
1075
 
 
1076
                field = rec_get_nth_field_old(rec, 5, &len);
 
1077
                foreign->referenced_col_names[i] = mem_heap_strdupl(
 
1078
                        foreign->heap, (char*) field, len);
 
1079
 
 
1080
                btr_pcur_move_to_next_user_rec(&pcur, &mtr);
 
1081
        }
 
1082
 
 
1083
        btr_pcur_close(&pcur);
 
1084
        mtr_commit(&mtr);
 
1085
}
 
1086
 
 
1087
/***************************************************************************
 
1088
Loads a foreign key constraint to the dictionary cache. */
 
1089
static
 
1090
ulint
 
1091
dict_load_foreign(
 
1092
/*==============*/
 
1093
                                /* out: DB_SUCCESS or error code */
 
1094
        const char*     id,     /* in: foreign constraint id as a
 
1095
                                null-terminated string */
 
1096
        ibool           check_charsets)
 
1097
                                /* in: TRUE=check charset compatibility */
 
1098
{
 
1099
        dict_foreign_t* foreign;
 
1100
        dict_table_t*   sys_foreign;
 
1101
        btr_pcur_t      pcur;
 
1102
        dict_index_t*   sys_index;
 
1103
        dtuple_t*       tuple;
 
1104
        mem_heap_t*     heap2;
 
1105
        dfield_t*       dfield;
 
1106
        rec_t*          rec;
 
1107
        byte*           field;
 
1108
        ulint           len;
 
1109
        ulint           n_fields_and_type;
 
1110
        mtr_t           mtr;
 
1111
 
 
1112
        ut_ad(mutex_own(&(dict_sys->mutex)));
 
1113
 
 
1114
        heap2 = mem_heap_create(1000);
 
1115
 
 
1116
        mtr_start(&mtr);
 
1117
 
 
1118
        sys_foreign = dict_table_get_low("SYS_FOREIGN");
 
1119
        sys_index = UT_LIST_GET_FIRST(sys_foreign->indexes);
 
1120
        ut_a(!dict_table_is_comp(sys_foreign));
 
1121
 
 
1122
        tuple = dtuple_create(heap2, 1);
 
1123
        dfield = dtuple_get_nth_field(tuple, 0);
 
1124
 
 
1125
        dfield_set_data(dfield, id, ut_strlen(id));
 
1126
        dict_index_copy_types(tuple, sys_index, 1);
 
1127
 
 
1128
        btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
 
1129
                                  BTR_SEARCH_LEAF, &pcur, &mtr);
 
1130
        rec = btr_pcur_get_rec(&pcur);
 
1131
 
 
1132
        if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
 
1133
            || rec_get_deleted_flag(rec, 0)) {
 
1134
                /* Not found */
 
1135
 
 
1136
                fprintf(stderr,
 
1137
                        "InnoDB: Error A: cannot load foreign constraint %s\n",
 
1138
                        id);
 
1139
 
 
1140
                btr_pcur_close(&pcur);
 
1141
                mtr_commit(&mtr);
 
1142
                mem_heap_free(heap2);
 
1143
 
 
1144
                return(DB_ERROR);
 
1145
        }
 
1146
 
 
1147
        field = rec_get_nth_field_old(rec, 0, &len);
 
1148
 
 
1149
        /* Check if the id in record is the searched one */
 
1150
        if (len != ut_strlen(id) || ut_memcmp(id, field, len) != 0) {
 
1151
 
 
1152
                fprintf(stderr,
 
1153
                        "InnoDB: Error B: cannot load foreign constraint %s\n",
 
1154
                        id);
 
1155
 
 
1156
                btr_pcur_close(&pcur);
 
1157
                mtr_commit(&mtr);
 
1158
                mem_heap_free(heap2);
 
1159
 
 
1160
                return(DB_ERROR);
 
1161
        }
 
1162
 
 
1163
        /* Read the table names and the number of columns associated
 
1164
        with the constraint */
 
1165
 
 
1166
        mem_heap_free(heap2);
 
1167
 
 
1168
        foreign = dict_mem_foreign_create();
 
1169
 
 
1170
        n_fields_and_type = mach_read_from_4(
 
1171
                rec_get_nth_field_old(rec, 5, &len));
 
1172
 
 
1173
        ut_a(len == 4);
 
1174
 
 
1175
        /* We store the type in the bits 24..29 of n_fields_and_type. */
 
1176
 
 
1177
        foreign->type = (unsigned int) (n_fields_and_type >> 24);
 
1178
        foreign->n_fields = (unsigned int) (n_fields_and_type & 0x3FFUL);
 
1179
 
 
1180
        foreign->id = mem_heap_strdup(foreign->heap, id);
 
1181
 
 
1182
        field = rec_get_nth_field_old(rec, 3, &len);
 
1183
        foreign->foreign_table_name = mem_heap_strdupl(
 
1184
                foreign->heap, (char*) field, len);
 
1185
 
 
1186
        field = rec_get_nth_field_old(rec, 4, &len);
 
1187
        foreign->referenced_table_name = mem_heap_strdupl(
 
1188
                foreign->heap, (char*) field, len);
 
1189
 
 
1190
        btr_pcur_close(&pcur);
 
1191
        mtr_commit(&mtr);
 
1192
 
 
1193
        dict_load_foreign_cols(id, foreign);
 
1194
 
 
1195
        /* If the foreign table is not yet in the dictionary cache, we
 
1196
        have to load it so that we are able to make type comparisons
 
1197
        in the next function call. */
 
1198
 
 
1199
        dict_table_get_low(foreign->foreign_table_name);
 
1200
 
 
1201
        /* Note that there may already be a foreign constraint object in
 
1202
        the dictionary cache for this constraint: then the following
 
1203
        call only sets the pointers in it to point to the appropriate table
 
1204
        and index objects and frees the newly created object foreign.
 
1205
        Adding to the cache should always succeed since we are not creating
 
1206
        a new foreign key constraint but loading one from the data
 
1207
        dictionary. */
 
1208
 
 
1209
        return(dict_foreign_add_to_cache(foreign, check_charsets));
 
1210
}
 
1211
 
 
1212
/***************************************************************************
 
1213
Loads foreign key constraints where the table is either the foreign key
 
1214
holder or where the table is referenced by a foreign key. Adds these
 
1215
constraints to the data dictionary. Note that we know that the dictionary
 
1216
cache already contains all constraints where the other relevant table is
 
1217
already in the dictionary cache. */
 
1218
 
 
1219
ulint
 
1220
dict_load_foreigns(
 
1221
/*===============*/
 
1222
                                        /* out: DB_SUCCESS or error code */
 
1223
        const char*     table_name,     /* in: table name */
 
1224
        ibool           check_charsets) /* in: TRUE=check charset
 
1225
                                        compatibility */
 
1226
{
 
1227
        btr_pcur_t      pcur;
 
1228
        mem_heap_t*     heap;
 
1229
        dtuple_t*       tuple;
 
1230
        dfield_t*       dfield;
 
1231
        dict_index_t*   sec_index;
 
1232
        dict_table_t*   sys_foreign;
 
1233
        rec_t*          rec;
 
1234
        byte*           field;
 
1235
        ulint           len;
 
1236
        char*           id ;
 
1237
        ulint           err;
 
1238
        mtr_t           mtr;
 
1239
 
 
1240
        ut_ad(mutex_own(&(dict_sys->mutex)));
 
1241
 
 
1242
        sys_foreign = dict_table_get_low("SYS_FOREIGN");
 
1243
 
 
1244
        if (sys_foreign == NULL) {
 
1245
                /* No foreign keys defined yet in this database */
 
1246
 
 
1247
                fprintf(stderr,
 
1248
                        "InnoDB: Error: no foreign key system tables"
 
1249
                        " in the database\n");
 
1250
 
 
1251
                return(DB_ERROR);
 
1252
        }
 
1253
 
 
1254
        ut_a(!dict_table_is_comp(sys_foreign));
 
1255
        mtr_start(&mtr);
 
1256
 
 
1257
        /* Get the secondary index based on FOR_NAME from table
 
1258
        SYS_FOREIGN */
 
1259
 
 
1260
        sec_index = dict_table_get_next_index(
 
1261
                dict_table_get_first_index(sys_foreign));
 
1262
start_load:
 
1263
        heap = mem_heap_create(256);
 
1264
 
 
1265
        tuple  = dtuple_create(heap, 1);
 
1266
        dfield = dtuple_get_nth_field(tuple, 0);
 
1267
 
 
1268
        dfield_set_data(dfield, table_name, ut_strlen(table_name));
 
1269
        dict_index_copy_types(tuple, sec_index, 1);
 
1270
 
 
1271
        btr_pcur_open_on_user_rec(sec_index, tuple, PAGE_CUR_GE,
 
1272
                                  BTR_SEARCH_LEAF, &pcur, &mtr);
 
1273
loop:
 
1274
        rec = btr_pcur_get_rec(&pcur);
 
1275
 
 
1276
        if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
 
1277
                /* End of index */
 
1278
 
 
1279
                goto load_next_index;
 
1280
        }
 
1281
 
 
1282
        /* Now we have the record in the secondary index containing a table
 
1283
        name and a foreign constraint ID */
 
1284
 
 
1285
        rec = btr_pcur_get_rec(&pcur);
 
1286
        field = rec_get_nth_field_old(rec, 0, &len);
 
1287
 
 
1288
        /* Check if the table name in the record is the one searched for; the
 
1289
        following call does the comparison in the latin1_swedish_ci
 
1290
        charset-collation, in a case-insensitive way. */
 
1291
 
 
1292
        if (0 != cmp_data_data(dfield_get_type(dfield)->mtype,
 
1293
                               dfield_get_type(dfield)->prtype,
 
1294
                               dfield_get_data(dfield), dfield_get_len(dfield),
 
1295
                               field, len)) {
 
1296
 
 
1297
                goto load_next_index;
 
1298
        }
 
1299
 
 
1300
        /* Since table names in SYS_FOREIGN are stored in a case-insensitive
 
1301
        order, we have to check that the table name matches also in a binary
 
1302
        string comparison. On Unix, MySQL allows table names that only differ
 
1303
        in character case. */
 
1304
 
 
1305
        if (0 != ut_memcmp(field, table_name, len)) {
 
1306
 
 
1307
                goto next_rec;
 
1308
        }
 
1309
 
 
1310
        if (rec_get_deleted_flag(rec, 0)) {
 
1311
 
 
1312
                goto next_rec;
 
1313
        }
 
1314
 
 
1315
        /* Now we get a foreign key constraint id */
 
1316
        field = rec_get_nth_field_old(rec, 1, &len);
 
1317
        id = mem_heap_strdupl(heap, (char*) field, len);
 
1318
 
 
1319
        btr_pcur_store_position(&pcur, &mtr);
 
1320
 
 
1321
        mtr_commit(&mtr);
 
1322
 
 
1323
        /* Load the foreign constraint definition to the dictionary cache */
 
1324
 
 
1325
        err = dict_load_foreign(id, check_charsets);
 
1326
 
 
1327
        if (err != DB_SUCCESS) {
 
1328
                btr_pcur_close(&pcur);
 
1329
                mem_heap_free(heap);
 
1330
 
 
1331
                return(err);
 
1332
        }
 
1333
 
 
1334
        mtr_start(&mtr);
 
1335
 
 
1336
        btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
 
1337
next_rec:
 
1338
        btr_pcur_move_to_next_user_rec(&pcur, &mtr);
 
1339
 
 
1340
        goto loop;
 
1341
 
 
1342
load_next_index:
 
1343
        btr_pcur_close(&pcur);
 
1344
        mtr_commit(&mtr);
 
1345
        mem_heap_free(heap);
 
1346
 
 
1347
        sec_index = dict_table_get_next_index(sec_index);
 
1348
 
 
1349
        if (sec_index != NULL) {
 
1350
 
 
1351
                mtr_start(&mtr);
 
1352
 
 
1353
                goto start_load;
 
1354
        }
 
1355
 
 
1356
        return(DB_SUCCESS);
 
1357
}