~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

Tags: innodb-plugin-1.0.1
Imported 1.0.1 with clean - with no changes.

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