~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2010-08-09 18:04:12 UTC
  • mfrom: (1689.3.7 staging)
  • Revision ID: brian@gaz-20100809180412-olurwh51ojllev6p
Merge in heap conversion, and case insensitive patch, and remove need for
M_HASH in session.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (C) 1996, 2010, Innobase Oy. All Rights Reserved.
 
3
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
4
4
 
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
11
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
12
 
13
13
You should have received a copy of the GNU General Public License along with
14
 
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
 
St, Fifth Floor, Boston, MA 02110-1301 USA
 
14
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
15
Place, Suite 330, Boston, MA 02111-1307 USA
16
16
 
17
17
*****************************************************************************/
18
18
 
45
45
#include "srv0start.h"
46
46
#include "srv0srv.h"
47
47
 
48
 
 
49
 
/** Following are six InnoDB system tables */
50
 
static const char* SYSTEM_TABLE_NAME[] = {
51
 
        "SYS_TABLES",
52
 
        "SYS_INDEXES",
53
 
        "SYS_COLUMNS",
54
 
        "SYS_FIELDS",
55
 
        "SYS_FOREIGN",
56
 
        "SYS_FOREIGN_COLS"
57
 
};
58
48
/****************************************************************//**
59
49
Compare the name of an index column.
60
50
@return TRUE if the i'th column of index is 'name'. */
165
155
dict_print(void)
166
156
/*============*/
167
157
{
 
158
        dict_table_t*   sys_tables;
 
159
        dict_index_t*   sys_index;
168
160
        dict_table_t*   table;
169
161
        btr_pcur_t      pcur;
170
162
        const rec_t*    rec;
171
 
        mem_heap_t*     heap;
 
163
        const byte*     field;
 
164
        ulint           len;
172
165
        mtr_t           mtr;
173
166
 
174
167
        /* Enlarge the fatal semaphore wait timeout during the InnoDB table
178
171
        srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
179
172
        mutex_exit(&kernel_mutex);
180
173
 
181
 
        heap = mem_heap_create(1000);
182
174
        mutex_enter(&(dict_sys->mutex));
183
175
 
184
176
        mtr_start(&mtr);
185
177
 
186
 
        rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
187
 
 
188
 
        while (rec) {
189
 
                const char* err_msg;
190
 
 
191
 
                err_msg = dict_process_sys_tables_rec(
192
 
                        heap, rec, &table,
193
 
                        static_cast<dict_table_info>(DICT_TABLE_LOAD_FROM_CACHE
194
 
                        | DICT_TABLE_UPDATE_STATS));
195
 
 
196
 
                mtr_commit(&mtr);
197
 
 
198
 
                if (!err_msg) {
 
178
        sys_tables = dict_table_get_low("SYS_TABLES");
 
179
        sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
 
180
 
 
181
        btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
 
182
                                    TRUE, &mtr);
 
183
loop:
 
184
        btr_pcur_move_to_next_user_rec(&pcur, &mtr);
 
185
 
 
186
        rec = btr_pcur_get_rec(&pcur);
 
187
 
 
188
        if (!btr_pcur_is_on_user_rec(&pcur)) {
 
189
                /* end of index */
 
190
 
 
191
                btr_pcur_close(&pcur);
 
192
                mtr_commit(&mtr);
 
193
 
 
194
                mutex_exit(&(dict_sys->mutex));
 
195
 
 
196
                /* Restore the fatal semaphore wait timeout */
 
197
 
 
198
                mutex_enter(&kernel_mutex);
 
199
                srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
 
200
                mutex_exit(&kernel_mutex);
 
201
 
 
202
                return;
 
203
        }
 
204
 
 
205
        field = rec_get_nth_field_old(rec, 0, &len);
 
206
 
 
207
        if (!rec_get_deleted_flag(rec, 0)) {
 
208
 
 
209
                /* We found one */
 
210
 
 
211
                char*   table_name = mem_strdupl((char*) field, len);
 
212
 
 
213
                btr_pcur_store_position(&pcur, &mtr);
 
214
 
 
215
                mtr_commit(&mtr);
 
216
 
 
217
                table = dict_table_get_low(table_name);
 
218
                mem_free(table_name);
 
219
 
 
220
                if (table == NULL) {
 
221
                        fputs("InnoDB: Failed to load table ", stderr);
 
222
                        ut_print_namel(stderr, NULL, TRUE, (char*) field, len);
 
223
                        putc('\n', stderr);
 
224
                } else {
 
225
                        /* The table definition was corrupt if there
 
226
                        is no index */
 
227
 
 
228
                        if (dict_table_get_first_index(table)) {
 
229
                                dict_update_statistics_low(table, TRUE);
 
230
                        }
 
231
 
199
232
                        dict_table_print_low(table);
200
 
                } else {
201
 
                        ut_print_timestamp(stderr);
202
 
                        fprintf(stderr, "  InnoDB: %s\n", err_msg);
203
233
                }
204
234
 
205
 
                mem_heap_empty(heap);
206
 
 
207
235
                mtr_start(&mtr);
208
 
                rec = dict_getnext_system(&pcur, &mtr);
209
 
        }
210
 
 
211
 
        mtr_commit(&mtr);
212
 
        mutex_exit(&(dict_sys->mutex));
213
 
        mem_heap_free(heap);
214
 
 
215
 
        /* Restore the fatal semaphore wait timeout */
216
 
        mutex_enter(&kernel_mutex);
217
 
        srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
218
 
        mutex_exit(&kernel_mutex);
219
 
}
220
 
 
221
 
 
222
 
/********************************************************************//**
223
 
This function gets the next system table record as it scans the table.
224
 
@return the next record if found, NULL if end of scan */
225
 
static
226
 
const rec_t*
227
 
dict_getnext_system_low(
228
 
/*====================*/
229
 
        btr_pcur_t*     pcur,           /*!< in/out: persistent cursor to the
230
 
                                        record*/
231
 
        mtr_t*          mtr)            /*!< in: the mini-transaction */
232
 
{
233
 
        rec_t*  rec = NULL;
234
 
 
235
 
        while (!rec || rec_get_deleted_flag(rec, 0)) {
236
 
                btr_pcur_move_to_next_user_rec(pcur, mtr);
237
 
 
238
 
                rec = btr_pcur_get_rec(pcur);
239
 
 
240
 
                if (!btr_pcur_is_on_user_rec(pcur)) {
241
 
                        /* end of index */
242
 
                        btr_pcur_close(pcur);
243
 
 
244
 
                        return(NULL);
245
 
                }
246
 
        }
247
 
 
248
 
        /* Get a record, let's save the position */
249
 
        btr_pcur_store_position(pcur, mtr);
250
 
 
251
 
        return(rec);
252
 
}
253
 
 
254
 
/********************************************************************//**
255
 
This function opens a system table, and return the first record.
256
 
@return first record of the system table */
257
 
UNIV_INTERN
258
 
const rec_t*
259
 
dict_startscan_system(
260
 
/*==================*/
261
 
        btr_pcur_t*     pcur,           /*!< out: persistent cursor to
262
 
                                        the record */
263
 
        mtr_t*          mtr,            /*!< in: the mini-transaction */
264
 
        dict_system_id_t system_id)     /*!< in: which system table to open */
265
 
{
266
 
        dict_table_t*   system_table;
267
 
        dict_index_t*   clust_index;
268
 
        const rec_t*    rec;
269
 
 
270
 
        ut_a(system_id < SYS_NUM_SYSTEM_TABLES);
271
 
 
272
 
        system_table = dict_table_get_low(SYSTEM_TABLE_NAME[system_id]);
273
 
 
274
 
        clust_index = UT_LIST_GET_FIRST(system_table->indexes);
275
 
 
276
 
        btr_pcur_open_at_index_side(TRUE, clust_index, BTR_SEARCH_LEAF, pcur,
277
 
                                    TRUE, mtr);
278
 
 
279
 
        rec = dict_getnext_system_low(pcur, mtr);
280
 
 
281
 
        return(rec);
282
 
}
283
 
 
284
 
/********************************************************************//**
285
 
This function gets the next system table record as it scans the table.
286
 
@return the next record if found, NULL if end of scan */
287
 
UNIV_INTERN
288
 
const rec_t*
289
 
dict_getnext_system(
290
 
/*================*/
291
 
        btr_pcur_t*     pcur,           /*!< in/out: persistent cursor
292
 
                                        to the record */
293
 
        mtr_t*          mtr)            /*!< in: the mini-transaction */
294
 
{
295
 
        const rec_t*    rec;
296
 
 
297
 
        /* Restore the position */
298
 
        btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, mtr);
299
 
 
300
 
        /* Get the next record */
301
 
        rec = dict_getnext_system_low(pcur, mtr);
302
 
 
303
 
        return(rec);
304
 
}
305
 
/********************************************************************//**
306
 
This function processes one SYS_TABLES record and populate the dict_table_t
307
 
struct for the table. Extracted out of dict_print() to be used by
308
 
both monitor table output and information schema innodb_sys_tables output.
309
 
@return error message, or NULL on success */
310
 
UNIV_INTERN
311
 
const char*
312
 
dict_process_sys_tables_rec(
313
 
/*========================*/
314
 
        mem_heap_t*     heap,           /*!< in/out: temporary memory heap */
315
 
        const rec_t*    rec,            /*!< in: SYS_TABLES record */
316
 
        dict_table_t**  table,          /*!< out: dict_table_t to fill */
317
 
        dict_table_info_t status)       /*!< in: status bit controls
318
 
                                        options such as whether we shall
319
 
                                        look for dict_table_t from cache
320
 
                                        first */
321
 
{
322
 
        ulint           len;
323
 
        const char*     field;
324
 
        const char*     err_msg = NULL;
325
 
        char*           table_name;
326
 
 
327
 
        field = (const char*) rec_get_nth_field_old(rec, 0, &len);
328
 
 
329
 
        ut_a(!rec_get_deleted_flag(rec, 0));
330
 
 
331
 
        /* Get the table name */
332
 
        table_name = mem_heap_strdupl(heap, (const char*)field, len);
333
 
 
334
 
        /* If DICT_TABLE_LOAD_FROM_CACHE is set, first check
335
 
        whether there is cached dict_table_t struct first */
336
 
        if (status & DICT_TABLE_LOAD_FROM_CACHE) {
337
 
                *table = dict_table_get_low(table_name);
338
 
 
339
 
                if (!(*table)) {
340
 
                        err_msg = "Table not found in cache";
341
 
                }
342
 
        } else {
343
 
                err_msg = dict_load_table_low(table_name, rec, table);
344
 
        }
345
 
 
346
 
        if (err_msg) {
347
 
                return(err_msg);
348
 
        }
349
 
 
350
 
        if ((status & DICT_TABLE_UPDATE_STATS)
351
 
            && dict_table_get_first_index(*table)) {
352
 
 
353
 
                /* Update statistics if DICT_TABLE_UPDATE_STATS
354
 
                is set */
355
 
                dict_update_statistics(*table,
356
 
                                       FALSE /* update even if
357
 
                                                initialized */);
358
 
        }
359
 
 
360
 
        return(NULL);
361
 
}
362
 
 
363
 
/********************************************************************//**
364
 
This function parses a SYS_INDEXES record and populate a dict_index_t
365
 
structure with the information from the record. For detail information
366
 
about SYS_INDEXES fields, please refer to dict_boot() function.
367
 
@return error message, or NULL on success */
368
 
UNIV_INTERN
369
 
const char*
370
 
dict_process_sys_indexes_rec(
371
 
/*=========================*/
372
 
        mem_heap_t*     heap,           /*!< in/out: heap memory */
373
 
        const rec_t*    rec,            /*!< in: current SYS_INDEXES rec */
374
 
        dict_index_t*   index,          /*!< out: index to be filled */
375
 
        table_id_t*     table_id)       /*!< out: index table id */
376
 
{
377
 
        const char*     err_msg;
378
 
        byte*           buf;
379
 
 
380
 
        buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
381
 
 
382
 
        /* Parse the record, and get "dict_index_t" struct filled */
383
 
        err_msg = dict_load_index_low(buf, NULL,
384
 
                                      heap, rec, FALSE, &index);
385
 
 
386
 
        *table_id = mach_read_from_8(buf);
387
 
 
388
 
        return(err_msg);
389
 
}
390
 
/********************************************************************//**
391
 
This function parses a SYS_COLUMNS record and populate a dict_column_t
392
 
structure with the information from the record.
393
 
@return error message, or NULL on success */
394
 
UNIV_INTERN
395
 
const char*
396
 
dict_process_sys_columns_rec(
397
 
/*=========================*/
398
 
        mem_heap_t*     heap,           /*!< in/out: heap memory */
399
 
        const rec_t*    rec,            /*!< in: current SYS_COLUMNS rec */
400
 
        dict_col_t*     column,         /*!< out: dict_col_t to be filled */
401
 
        table_id_t*     table_id,       /*!< out: table id */
402
 
        const char**    col_name)       /*!< out: column name */
403
 
{
404
 
        const char*     err_msg;
405
 
 
406
 
        /* Parse the record, and get "dict_col_t" struct filled */
407
 
        err_msg = dict_load_column_low(NULL, heap, column,
408
 
                                       table_id, col_name, rec);
409
 
 
410
 
        return(err_msg);
411
 
}
412
 
/********************************************************************//**
413
 
This function parses a SYS_FIELDS record and populates a dict_field_t
414
 
structure with the information from the record.
415
 
@return error message, or NULL on success */
416
 
UNIV_INTERN
417
 
const char*
418
 
dict_process_sys_fields_rec(
419
 
/*========================*/
420
 
        mem_heap_t*     heap,           /*!< in/out: heap memory */
421
 
        const rec_t*    rec,            /*!< in: current SYS_FIELDS rec */
422
 
        dict_field_t*   sys_field,      /*!< out: dict_field_t to be
423
 
                                        filled */
424
 
        ulint*          pos,            /*!< out: Field position */
425
 
        index_id_t*     index_id,       /*!< out: current index id */
426
 
        index_id_t      last_id)        /*!< in: previous index id */
427
 
{
428
 
        byte*           buf;
429
 
        byte*           last_index_id;
430
 
        const char*     err_msg;
431
 
 
432
 
        buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
433
 
 
434
 
        last_index_id = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
435
 
        mach_write_to_8(last_index_id, last_id);
436
 
 
437
 
        err_msg = dict_load_field_low(buf, NULL, sys_field,
438
 
                                      pos, last_index_id, heap, rec);
439
 
 
440
 
        *index_id = mach_read_from_8(buf);
441
 
 
442
 
        return(err_msg);
443
 
 
444
 
}
445
 
/********************************************************************//**
446
 
This function parses a SYS_FOREIGN record and populate a dict_foreign_t
447
 
structure with the information from the record. For detail information
448
 
about SYS_FOREIGN fields, please refer to dict_load_foreign() function
449
 
@return error message, or NULL on success */
450
 
UNIV_INTERN
451
 
const char*
452
 
dict_process_sys_foreign_rec(
453
 
/*=========================*/
454
 
        mem_heap_t*     heap,           /*!< in/out: heap memory */
455
 
        const rec_t*    rec,            /*!< in: current SYS_FOREIGN rec */
456
 
        dict_foreign_t* foreign)        /*!< out: dict_foreign_t struct
457
 
                                        to be filled */
458
 
{
459
 
        ulint           len;
460
 
        const byte*     field;
461
 
        ulint           n_fields_and_type;
462
 
 
463
 
        if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
464
 
                return("delete-marked record in SYS_FOREIGN");
465
 
        }
466
 
 
467
 
        if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 6)) {
468
 
                return("wrong number of columns in SYS_FOREIGN record");
469
 
        }
470
 
 
471
 
        field = rec_get_nth_field_old(rec, 0/*ID*/, &len);
472
 
        if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
473
 
err_len:
474
 
                return("incorrect column length in SYS_FOREIGN");
475
 
        }
476
 
        foreign->id = mem_heap_strdupl(heap, (const char*) field, len);
477
 
 
478
 
        rec_get_nth_field_offs_old(rec, 1/*DB_TRX_ID*/, &len);
479
 
        if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
480
 
                goto err_len;
481
 
        }
482
 
        rec_get_nth_field_offs_old(rec, 2/*DB_ROLL_PTR*/, &len);
483
 
        if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
484
 
                goto err_len;
485
 
        }
486
 
 
487
 
        field = rec_get_nth_field_old(rec, 3/*FOR_NAME*/, &len);
488
 
        if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
489
 
                goto err_len;
490
 
        }
491
 
        foreign->foreign_table_name = mem_heap_strdupl(
492
 
                heap, (const char*) field, len);
493
 
 
494
 
        field = rec_get_nth_field_old(rec, 4/*REF_NAME*/, &len);
495
 
        if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
496
 
                goto err_len;
497
 
        }
498
 
        foreign->referenced_table_name = mem_heap_strdupl(
499
 
                heap, (const char*) field, len);
500
 
 
501
 
        field = rec_get_nth_field_old(rec, 5/*N_COLS*/, &len);
502
 
        if (UNIV_UNLIKELY(len != 4)) {
503
 
                goto err_len;
504
 
        }
505
 
        n_fields_and_type = mach_read_from_4(field);
506
 
 
507
 
        foreign->type = (unsigned int) (n_fields_and_type >> 24);
508
 
        foreign->n_fields = (unsigned int) (n_fields_and_type & 0x3FFUL);
509
 
 
510
 
        return(NULL);
511
 
}
512
 
/********************************************************************//**
513
 
This function parses a SYS_FOREIGN_COLS record and extract necessary
514
 
information from the record and return to caller.
515
 
@return error message, or NULL on success */
516
 
UNIV_INTERN
517
 
const char*
518
 
dict_process_sys_foreign_col_rec(
519
 
/*=============================*/
520
 
        mem_heap_t*     heap,           /*!< in/out: heap memory */
521
 
        const rec_t*    rec,            /*!< in: current SYS_FOREIGN_COLS rec */
522
 
        const char**    name,           /*!< out: foreign key constraint name */
523
 
        const char**    for_col_name,   /*!< out: referencing column name */
524
 
        const char**    ref_col_name,   /*!< out: referenced column name
525
 
                                        in referenced table */
526
 
        ulint*          pos)            /*!< out: column position */
527
 
{
528
 
        ulint           len;
529
 
        const byte*     field;
530
 
 
531
 
        if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
532
 
                return("delete-marked record in SYS_FOREIGN_COLS");
533
 
        }
534
 
 
535
 
        if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 6)) {
536
 
                return("wrong number of columns in SYS_FOREIGN_COLS record");
537
 
        }
538
 
 
539
 
        field = rec_get_nth_field_old(rec, 0/*ID*/, &len);
540
 
        if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
541
 
err_len:
542
 
                return("incorrect column length in SYS_FOREIGN_COLS");
543
 
        }
544
 
        *name = mem_heap_strdupl(heap, (char*) field, len);
545
 
 
546
 
        field = rec_get_nth_field_old(rec, 1/*POS*/, &len);
547
 
        if (UNIV_UNLIKELY(len != 4)) {
548
 
                goto err_len;
549
 
        }
550
 
        *pos = mach_read_from_4(field);
551
 
 
552
 
        rec_get_nth_field_offs_old(rec, 2/*DB_TRX_ID*/, &len);
553
 
        if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
554
 
                goto err_len;
555
 
        }
556
 
        rec_get_nth_field_offs_old(rec, 3/*DB_ROLL_PTR*/, &len);
557
 
        if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
558
 
                goto err_len;
559
 
        }
560
 
 
561
 
        field = rec_get_nth_field_old(rec, 4/*FOR_COL_NAME*/, &len);
562
 
        if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
563
 
                goto err_len;
564
 
        }
565
 
        *for_col_name = mem_heap_strdupl(heap, (char*) field, len);
566
 
 
567
 
        field = rec_get_nth_field_old(rec, 5/*REF_COL_NAME*/, &len);
568
 
        if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
569
 
                goto err_len;
570
 
        }
571
 
        *ref_col_name = mem_heap_strdupl(heap, (char*) field, len);
572
 
 
573
 
        return(NULL);
 
236
 
 
237
                btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
 
238
        }
 
239
 
 
240
        goto loop;
574
241
}
575
242
 
576
243
/*
672
339
                return(0);
673
340
        }
674
341
 
675
 
        field = rec_get_nth_field_old(rec, 4/*N_COLS*/, &len);
 
342
        field = rec_get_nth_field_old(rec, 4, &len);
676
343
        n_cols = mach_read_from_4(field);
677
344
 
678
345
        if (UNIV_UNLIKELY(!(n_cols & 0x80000000UL))) {
702
369
                return(ULINT_UNDEFINED);
703
370
        }
704
371
 
705
 
        if (UNIV_UNLIKELY(flags & (SIZE_MAX << DICT_TF_BITS))) {
 
372
        if (UNIV_UNLIKELY(flags & (~0 << DICT_TF_BITS))) {
706
373
                /* Some unused bits are set. */
707
374
                return(ULINT_UNDEFINED);
708
375
        }
728
395
        dict_index_t*   sys_index;
729
396
        btr_pcur_t      pcur;
730
397
        const rec_t*    rec;
731
 
        ulint           max_space_id;
 
398
        ulint           max_space_id    = 0;
732
399
        mtr_t           mtr;
733
400
 
734
401
        mutex_enter(&(dict_sys->mutex));
739
406
        sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
740
407
        ut_a(!dict_table_is_comp(sys_tables));
741
408
 
742
 
        max_space_id = mtr_read_ulint(dict_hdr_get(&mtr)
743
 
                                      + DICT_HDR_MAX_SPACE_ID,
744
 
                                      MLOG_4BYTES, &mtr);
745
 
        fil_set_max_space_id_if_bigger(max_space_id);
746
 
 
747
409
        btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
748
410
                                    TRUE, &mtr);
749
411
loop:
807
469
 
808
470
                mtr_commit(&mtr);
809
471
 
810
 
                if (space_id == 0) {
811
 
                        /* The system tablespace always exists. */
812
 
                } else if (in_crash_recovery) {
 
472
                if (space_id != 0 && in_crash_recovery) {
813
473
                        /* Check that the tablespace (the .ibd file) really
814
 
                        exists; print a warning to the .err log if not.
815
 
                        Do not print warnings for temporary tables. */
816
 
                        ibool   is_temp;
817
 
 
818
 
                        field = rec_get_nth_field_old(rec, 4, &len);
819
 
                        if (0x80000000UL &  mach_read_from_4(field)) {
820
 
                                /* ROW_FORMAT=COMPACT: read the is_temp
821
 
                                flag from SYS_TABLES.MIX_LEN. */
822
 
                                field = rec_get_nth_field_old(rec, 7, &len);
823
 
                                is_temp = mach_read_from_4(field)
824
 
                                        & DICT_TF2_TEMPORARY;
825
 
                        } else {
826
 
                                /* For tables created with old versions
827
 
                                of InnoDB, SYS_TABLES.MIX_LEN may contain
828
 
                                garbage.  Such tables would always be
829
 
                                in ROW_FORMAT=REDUNDANT.  Pretend that
830
 
                                all such tables are non-temporary.  That is,
831
 
                                do not suppress error printouts about
832
 
                                temporary tables not being found. */
833
 
                                is_temp = FALSE;
834
 
                        }
835
 
 
836
 
                        fil_space_for_table_exists_in_mem(
837
 
                                space_id, name, is_temp, TRUE, !is_temp);
838
 
                } else {
 
474
                        exists; print a warning to the .err log if not */
 
475
 
 
476
                        fil_space_for_table_exists_in_mem(space_id, name,
 
477
                                                          FALSE, TRUE, TRUE);
 
478
                }
 
479
 
 
480
                if (space_id != 0 && !in_crash_recovery) {
839
481
                        /* It is a normal database startup: create the space
840
482
                        object and check that the .ibd file exists. */
841
483
 
858
500
}
859
501
 
860
502
/********************************************************************//**
861
 
Loads a table column definition from a SYS_COLUMNS record to
862
 
dict_table_t.
863
 
@return error message, or NULL on success */
864
 
UNIV_INTERN
865
 
const char*
866
 
dict_load_column_low(
867
 
/*=================*/
868
 
        dict_table_t*   table,          /*!< in/out: table, could be NULL
869
 
                                        if we just populate a dict_column_t
870
 
                                        struct with information from
871
 
                                        a SYS_COLUMNS record */
872
 
        mem_heap_t*     heap,           /*!< in/out: memory heap
873
 
                                        for temporary storage */
874
 
        dict_col_t*     column,         /*!< out: dict_column_t to fill,
875
 
                                        or NULL if table != NULL */
876
 
        table_id_t*     table_id,       /*!< out: table id */
877
 
        const char**    col_name,       /*!< out: column name */
878
 
        const rec_t*    rec)            /*!< in: SYS_COLUMNS record */
 
503
Loads definitions for table columns. */
 
504
static
 
505
void
 
506
dict_load_columns(
 
507
/*==============*/
 
508
        dict_table_t*   table,  /*!< in: table */
 
509
        mem_heap_t*     heap)   /*!< in: memory heap for temporary storage */
879
510
{
 
511
        dict_table_t*   sys_columns;
 
512
        dict_index_t*   sys_index;
 
513
        btr_pcur_t      pcur;
 
514
        dtuple_t*       tuple;
 
515
        dfield_t*       dfield;
 
516
        const rec_t*    rec;
 
517
        const byte*     field;
 
518
        ulint           len;
 
519
        byte*           buf;
880
520
        char*           name;
881
 
        const byte*     field;
882
 
        ulint           len;
883
521
        ulint           mtype;
884
522
        ulint           prtype;
885
523
        ulint           col_len;
886
 
        ulint           pos = 0;
887
 
 
888
 
        ut_ad(table || column);
889
 
 
890
 
        if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
891
 
                return("delete-marked record in SYS_COLUMNS");
892
 
        }
893
 
 
894
 
        if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 9)) {
895
 
                return("wrong number of columns in SYS_COLUMNS record");
896
 
        }
897
 
 
898
 
        field = rec_get_nth_field_old(rec, 0/*TABLE_ID*/, &len);
899
 
        if (UNIV_UNLIKELY(len != 8)) {
900
 
err_len:
901
 
                return("incorrect column length in SYS_COLUMNS");
902
 
        }
903
 
 
904
 
        if (table_id) {
905
 
                *table_id = mach_read_from_8(field);
906
 
        } else if (UNIV_UNLIKELY(table->id != mach_read_from_8(field))) {
907
 
                return("SYS_COLUMNS.TABLE_ID mismatch");
908
 
        }
909
 
 
910
 
        field = rec_get_nth_field_old(rec, 1/*POS*/, &len);
911
 
        if (UNIV_UNLIKELY(len != 4)) {
912
 
 
913
 
                goto err_len;
914
 
        }
915
 
 
916
 
        pos = mach_read_from_4(field);
917
 
 
918
 
        if (UNIV_UNLIKELY(table && table->n_def != pos)) {
919
 
                return("SYS_COLUMNS.POS mismatch");
920
 
        }
921
 
 
922
 
        rec_get_nth_field_offs_old(rec, 2/*DB_TRX_ID*/, &len);
923
 
        if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
924
 
                goto err_len;
925
 
        }
926
 
        rec_get_nth_field_offs_old(rec, 3/*DB_ROLL_PTR*/, &len);
927
 
        if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
928
 
                goto err_len;
929
 
        }
930
 
 
931
 
        field = rec_get_nth_field_old(rec, 4/*NAME*/, &len);
932
 
        if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
933
 
                goto err_len;
934
 
        }
935
 
 
936
 
        name = mem_heap_strdupl(heap, (const char*) field, len);
937
 
 
938
 
        if (col_name) {
939
 
                *col_name = name;
940
 
        }
941
 
 
942
 
        field = rec_get_nth_field_old(rec, 5/*MTYPE*/, &len);
943
 
        if (UNIV_UNLIKELY(len != 4)) {
944
 
                goto err_len;
945
 
        }
946
 
 
947
 
        mtype = mach_read_from_4(field);
948
 
 
949
 
        field = rec_get_nth_field_old(rec, 6/*PRTYPE*/, &len);
950
 
        if (UNIV_UNLIKELY(len != 4)) {
951
 
                goto err_len;
952
 
        }
953
 
        prtype = mach_read_from_4(field);
954
 
 
955
 
        if (dtype_get_charset_coll(prtype) == 0
956
 
            && dtype_is_string_type(mtype)) {
957
 
                /* The table was created with < 4.1.2. */
958
 
 
959
 
                if (dtype_is_binary_string_type(mtype, prtype)) {
960
 
                        /* Use the binary collation for
961
 
                        string columns of binary type. */
962
 
 
963
 
                        prtype = dtype_form_prtype(
964
 
                                prtype,
965
 
                                DATA_MYSQL_BINARY_CHARSET_COLL);
966
 
                } else {
967
 
                        /* Use the default charset for
968
 
                        other than binary columns. */
969
 
 
970
 
                        prtype = dtype_form_prtype(
971
 
                                prtype,
972
 
                                data_mysql_default_charset_coll);
973
 
                }
974
 
        }
975
 
 
976
 
        field = rec_get_nth_field_old(rec, 7/*LEN*/, &len);
977
 
        if (UNIV_UNLIKELY(len != 4)) {
978
 
                goto err_len;
979
 
        }
980
 
        col_len = mach_read_from_4(field);
981
 
        field = rec_get_nth_field_old(rec, 8/*PREC*/, &len);
982
 
        if (UNIV_UNLIKELY(len != 4)) {
983
 
                goto err_len;
984
 
        }
985
 
 
986
 
        if (!column) {
987
 
                dict_mem_table_add_col(table, heap, name, mtype,
988
 
                                       prtype, col_len);
989
 
        } else {
990
 
                dict_mem_fill_column_struct(column, pos, mtype,
991
 
                                            prtype, col_len);
992
 
        }
993
 
 
994
 
        return(NULL);
995
 
}
996
 
 
997
 
/********************************************************************//**
998
 
Loads definitions for table columns. */
999
 
static
1000
 
void
1001
 
dict_load_columns(
1002
 
/*==============*/
1003
 
        dict_table_t*   table,  /*!< in/out: table */
1004
 
        mem_heap_t*     heap)   /*!< in/out: memory heap
1005
 
                                for temporary storage */
1006
 
{
1007
 
        dict_table_t*   sys_columns;
1008
 
        dict_index_t*   sys_index;
1009
 
        btr_pcur_t      pcur;
1010
 
        dtuple_t*       tuple;
1011
 
        dfield_t*       dfield;
1012
 
        const rec_t*    rec;
1013
 
        byte*           buf;
1014
524
        ulint           i;
1015
525
        mtr_t           mtr;
1016
526
 
1022
532
        sys_index = UT_LIST_GET_FIRST(sys_columns->indexes);
1023
533
        ut_a(!dict_table_is_comp(sys_columns));
1024
534
 
1025
 
        ut_a(name_of_col_is(sys_columns, sys_index, 4, "NAME"));
1026
 
        ut_a(name_of_col_is(sys_columns, sys_index, 8, "PREC"));
1027
 
 
1028
535
        tuple = dtuple_create(heap, 1);
1029
536
        dfield = dtuple_get_nth_field(tuple, 0);
1030
537
 
1031
 
        buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
 
538
        buf = mem_heap_alloc(heap, 8);
1032
539
        mach_write_to_8(buf, table->id);
1033
540
 
1034
541
        dfield_set_data(dfield, buf, 8);
1037
544
        btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
1038
545
                                  BTR_SEARCH_LEAF, &pcur, &mtr);
1039
546
        for (i = 0; i + DATA_N_SYS_COLS < (ulint) table->n_cols; i++) {
1040
 
                const char* err_msg;
1041
547
 
1042
548
                rec = btr_pcur_get_rec(&pcur);
1043
549
 
1044
550
                ut_a(btr_pcur_is_on_user_rec(&pcur));
1045
551
 
1046
 
                err_msg = dict_load_column_low(table, heap, NULL, NULL,
1047
 
                                               NULL, rec);
1048
 
 
1049
 
                if (err_msg) {
1050
 
                        fprintf(stderr, "InnoDB: %s\n", err_msg);
1051
 
                        ut_error;
 
552
                ut_a(!rec_get_deleted_flag(rec, 0));
 
553
 
 
554
                field = rec_get_nth_field_old(rec, 0, &len);
 
555
                ut_ad(len == 8);
 
556
                ut_a(ut_dulint_cmp(table->id, mach_read_from_8(field)) == 0);
 
557
 
 
558
                field = rec_get_nth_field_old(rec, 1, &len);
 
559
                ut_ad(len == 4);
 
560
                ut_a(i == mach_read_from_4(field));
 
561
 
 
562
                ut_a(name_of_col_is(sys_columns, sys_index, 4, "NAME"));
 
563
 
 
564
                field = rec_get_nth_field_old(rec, 4, &len);
 
565
                name = mem_heap_strdupl(heap, (char*) field, len);
 
566
 
 
567
                field = rec_get_nth_field_old(rec, 5, &len);
 
568
                mtype = mach_read_from_4(field);
 
569
 
 
570
                field = rec_get_nth_field_old(rec, 6, &len);
 
571
                prtype = mach_read_from_4(field);
 
572
 
 
573
                if (dtype_get_charset_coll(prtype) == 0
 
574
                    && dtype_is_string_type(mtype)) {
 
575
                        /* The table was created with < 4.1.2. */
 
576
 
 
577
                        if (dtype_is_binary_string_type(mtype, prtype)) {
 
578
                                /* Use the binary collation for
 
579
                                string columns of binary type. */
 
580
 
 
581
                                prtype = dtype_form_prtype(
 
582
                                        prtype,
 
583
                                        DATA_MYSQL_BINARY_CHARSET_COLL);
 
584
                        } else {
 
585
                                /* Use the default charset for
 
586
                                other than binary columns. */
 
587
 
 
588
                                prtype = dtype_form_prtype(
 
589
                                        prtype,
 
590
                                        data_mysql_default_charset_coll);
 
591
                        }
1052
592
                }
1053
593
 
 
594
                field = rec_get_nth_field_old(rec, 7, &len);
 
595
                col_len = mach_read_from_4(field);
 
596
 
 
597
                ut_a(name_of_col_is(sys_columns, sys_index, 8, "PREC"));
 
598
 
 
599
                dict_mem_table_add_col(table, heap, name,
 
600
                                       mtype, prtype, col_len);
1054
601
                btr_pcur_move_to_next_user_rec(&pcur, &mtr);
1055
602
        }
1056
603
 
1058
605
        mtr_commit(&mtr);
1059
606
}
1060
607
 
1061
 
/** Error message for a delete-marked record in dict_load_field_low() */
1062
 
static const char* dict_load_field_del = "delete-marked record in SYS_FIELDS";
1063
 
 
1064
 
/********************************************************************//**
1065
 
Loads an index field definition from a SYS_FIELDS record to
1066
 
dict_index_t.
1067
 
@return error message, or NULL on success */
1068
 
UNIV_INTERN
1069
 
const char*
1070
 
dict_load_field_low(
1071
 
/*================*/
1072
 
        byte*           index_id,       /*!< in/out: index id (8 bytes)
1073
 
                                        an "in" value if index != NULL
1074
 
                                        and "out" if index == NULL */
1075
 
        dict_index_t*   index,          /*!< in/out: index, could be NULL
1076
 
                                        if we just populate a dict_field_t
1077
 
                                        struct with information from
1078
 
                                        a SYS_FIELDSS record */
1079
 
        dict_field_t*   sys_field,      /*!< out: dict_field_t to be
1080
 
                                        filled */
1081
 
        ulint*          pos,            /*!< out: Field position */
1082
 
        byte*           last_index_id,  /*!< in: last index id */
1083
 
        mem_heap_t*     heap,           /*!< in/out: memory heap
1084
 
                                        for temporary storage */
1085
 
        const rec_t*    rec)            /*!< in: SYS_FIELDS record */
1086
 
{
1087
 
        const byte*     field;
1088
 
        ulint           len;
1089
 
        ulint           pos_and_prefix_len;
1090
 
        ulint           prefix_len;
1091
 
        ibool           first_field;
1092
 
        ulint           position;
1093
 
 
1094
 
        /* Either index or sys_field is supplied, not both */
1095
 
        ut_a((!index) || (!sys_field));
1096
 
 
1097
 
        if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
1098
 
                return(dict_load_field_del);
1099
 
        }
1100
 
 
1101
 
        if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 5)) {
1102
 
                return("wrong number of columns in SYS_FIELDS record");
1103
 
        }
1104
 
 
1105
 
        field = rec_get_nth_field_old(rec, 0/*INDEX_ID*/, &len);
1106
 
        if (UNIV_UNLIKELY(len != 8)) {
1107
 
err_len:
1108
 
                return("incorrect column length in SYS_FIELDS");
1109
 
        }
1110
 
 
1111
 
        if (!index) {
1112
 
                ut_a(last_index_id);
1113
 
                memcpy(index_id, (const char*)field, 8);
1114
 
                first_field = memcmp(index_id, last_index_id, 8);
1115
 
        } else {
1116
 
                first_field = (index->n_def == 0);
1117
 
                if (memcmp(field, index_id, 8)) {
1118
 
                        return("SYS_FIELDS.INDEX_ID mismatch");
1119
 
                }
1120
 
        }
1121
 
 
1122
 
        field = rec_get_nth_field_old(rec, 1/*POS*/, &len);
1123
 
        if (UNIV_UNLIKELY(len != 4)) {
1124
 
                goto err_len;
1125
 
        }
1126
 
 
1127
 
        rec_get_nth_field_offs_old(rec, 2/*DB_TRX_ID*/, &len);
1128
 
        if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
1129
 
                goto err_len;
1130
 
        }
1131
 
        rec_get_nth_field_offs_old(rec, 3/*DB_ROLL_PTR*/, &len);
1132
 
        if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
1133
 
                goto err_len;
1134
 
        }
1135
 
 
1136
 
        /* The next field stores the field position in the index and a
1137
 
        possible column prefix length if the index field does not
1138
 
        contain the whole column. The storage format is like this: if
1139
 
        there is at least one prefix field in the index, then the HIGH
1140
 
        2 bytes contain the field number (index->n_def) and the low 2
1141
 
        bytes the prefix length for the field. Otherwise the field
1142
 
        number (index->n_def) is contained in the 2 LOW bytes. */
1143
 
 
1144
 
        pos_and_prefix_len = mach_read_from_4(field);
1145
 
 
1146
 
        if (index && UNIV_UNLIKELY
1147
 
            ((pos_and_prefix_len & 0xFFFFUL) != index->n_def
1148
 
             && (pos_and_prefix_len >> 16 & 0xFFFF) != index->n_def)) {
1149
 
                return("SYS_FIELDS.POS mismatch");
1150
 
        }
1151
 
 
1152
 
        if (first_field || pos_and_prefix_len > 0xFFFFUL) {
1153
 
                prefix_len = pos_and_prefix_len & 0xFFFFUL;
1154
 
                position = (pos_and_prefix_len & 0xFFFF0000UL)  >> 16;
1155
 
        } else {
1156
 
                prefix_len = 0;
1157
 
                position = pos_and_prefix_len & 0xFFFFUL;
1158
 
        }
1159
 
 
1160
 
        field = rec_get_nth_field_old(rec, 4, &len);
1161
 
        if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
1162
 
                goto err_len;
1163
 
        }
1164
 
 
1165
 
        if (index) {
1166
 
                dict_mem_index_add_field(
1167
 
                        index, mem_heap_strdupl(heap, (const char*) field, len),
1168
 
                        prefix_len);
1169
 
        } else {
1170
 
                ut_a(sys_field);
1171
 
                ut_a(pos);
1172
 
 
1173
 
                sys_field->name = mem_heap_strdupl(
1174
 
                        heap, (const char*) field, len);
1175
 
                sys_field->prefix_len = prefix_len;
1176
 
                *pos = position;
1177
 
        }
1178
 
 
1179
 
        return(NULL);
1180
 
}
1181
 
 
1182
 
/********************************************************************//**
1183
 
Loads definitions for index fields.
1184
 
@return DB_SUCCESS if ok, DB_CORRUPTION if corruption */
 
608
/********************************************************************//**
 
609
Loads definitions for index fields. */
1185
610
static
1186
 
ulint
 
611
void
1187
612
dict_load_fields(
1188
613
/*=============*/
1189
 
        dict_index_t*   index,  /*!< in/out: index whose fields to load */
 
614
        dict_index_t*   index,  /*!< in: index whose fields to load */
1190
615
        mem_heap_t*     heap)   /*!< in: memory heap for temporary storage */
1191
616
{
1192
617
        dict_table_t*   sys_fields;
1194
619
        btr_pcur_t      pcur;
1195
620
        dtuple_t*       tuple;
1196
621
        dfield_t*       dfield;
 
622
        ulint           pos_and_prefix_len;
 
623
        ulint           prefix_len;
1197
624
        const rec_t*    rec;
 
625
        const byte*     field;
 
626
        ulint           len;
1198
627
        byte*           buf;
1199
628
        ulint           i;
1200
629
        mtr_t           mtr;
1201
 
        ulint           error;
1202
630
 
1203
631
        ut_ad(mutex_own(&(dict_sys->mutex)));
1204
632
 
1207
635
        sys_fields = dict_table_get_low("SYS_FIELDS");
1208
636
        sys_index = UT_LIST_GET_FIRST(sys_fields->indexes);
1209
637
        ut_a(!dict_table_is_comp(sys_fields));
1210
 
        ut_a(name_of_col_is(sys_fields, sys_index, 4, "COL_NAME"));
1211
638
 
1212
639
        tuple = dtuple_create(heap, 1);
1213
640
        dfield = dtuple_get_nth_field(tuple, 0);
1214
641
 
1215
 
        buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
 
642
        buf = mem_heap_alloc(heap, 8);
1216
643
        mach_write_to_8(buf, index->id);
1217
644
 
1218
645
        dfield_set_data(dfield, buf, 8);
1221
648
        btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
1222
649
                                  BTR_SEARCH_LEAF, &pcur, &mtr);
1223
650
        for (i = 0; i < index->n_fields; i++) {
1224
 
                const char* err_msg;
1225
651
 
1226
652
                rec = btr_pcur_get_rec(&pcur);
1227
653
 
1228
654
                ut_a(btr_pcur_is_on_user_rec(&pcur));
1229
655
 
1230
 
                err_msg = dict_load_field_low(buf, index, NULL, NULL, NULL,
1231
 
                                              heap, rec);
 
656
                /* There could be delete marked records in SYS_FIELDS
 
657
                because SYS_FIELDS.INDEX_ID can be updated
 
658
                by ALTER TABLE ADD INDEX. */
1232
659
 
1233
 
                if (err_msg == dict_load_field_del) {
1234
 
                        /* There could be delete marked records in
1235
 
                        SYS_FIELDS because SYS_FIELDS.INDEX_ID can be
1236
 
                        updated by ALTER TABLE ADD INDEX. */
 
660
                if (rec_get_deleted_flag(rec, 0)) {
1237
661
 
1238
662
                        goto next_rec;
1239
 
                } else if (err_msg) {
1240
 
                        fprintf(stderr, "InnoDB: %s\n", err_msg);
1241
 
                        error = DB_CORRUPTION;
1242
 
                        goto func_exit;
1243
 
                }
 
663
                }
 
664
 
 
665
                field = rec_get_nth_field_old(rec, 0, &len);
 
666
                ut_ad(len == 8);
 
667
 
 
668
                field = rec_get_nth_field_old(rec, 1, &len);
 
669
                ut_a(len == 4);
 
670
 
 
671
                /* The next field stores the field position in the index
 
672
                and a possible column prefix length if the index field
 
673
                does not contain the whole column. The storage format is
 
674
                like this: if there is at least one prefix field in the index,
 
675
                then the HIGH 2 bytes contain the field number (== i) and the
 
676
                low 2 bytes the prefix length for the field. Otherwise the
 
677
                field number (== i) is contained in the 2 LOW bytes. */
 
678
 
 
679
                pos_and_prefix_len = mach_read_from_4(field);
 
680
 
 
681
                ut_a((pos_and_prefix_len & 0xFFFFUL) == i
 
682
                     || (pos_and_prefix_len & 0xFFFF0000UL) == (i << 16));
 
683
 
 
684
                if ((i == 0 && pos_and_prefix_len > 0)
 
685
                    || (pos_and_prefix_len & 0xFFFF0000UL) > 0) {
 
686
 
 
687
                        prefix_len = pos_and_prefix_len & 0xFFFFUL;
 
688
                } else {
 
689
                        prefix_len = 0;
 
690
                }
 
691
 
 
692
                ut_a(name_of_col_is(sys_fields, sys_index, 4, "COL_NAME"));
 
693
 
 
694
                field = rec_get_nth_field_old(rec, 4, &len);
 
695
 
 
696
                dict_mem_index_add_field(index,
 
697
                                         mem_heap_strdupl(heap,
 
698
                                                          (char*) field, len),
 
699
                                         prefix_len);
 
700
 
1244
701
next_rec:
1245
702
                btr_pcur_move_to_next_user_rec(&pcur, &mtr);
1246
703
        }
1247
704
 
1248
 
        error = DB_SUCCESS;
1249
 
func_exit:
1250
705
        btr_pcur_close(&pcur);
1251
706
        mtr_commit(&mtr);
1252
 
        return(error);
1253
 
}
1254
 
 
1255
 
/** Error message for a delete-marked record in dict_load_index_low() */
1256
 
static const char* dict_load_index_del = "delete-marked record in SYS_INDEXES";
1257
 
/** Error message for table->id mismatch in dict_load_index_low() */
1258
 
static const char* dict_load_index_id_err = "SYS_INDEXES.TABLE_ID mismatch";
1259
 
 
1260
 
/********************************************************************//**
1261
 
Loads an index definition from a SYS_INDEXES record to dict_index_t.
1262
 
If allocate=TRUE, we will create a dict_index_t structure and fill it
1263
 
accordingly. If allocated=FALSE, the dict_index_t will be supplied by
1264
 
the caller and filled with information read from the record.  @return
1265
 
error message, or NULL on success */
1266
 
UNIV_INTERN
1267
 
const char*
1268
 
dict_load_index_low(
1269
 
/*================*/
1270
 
        byte*           table_id,       /*!< in/out: table id (8 bytes),
1271
 
                                        an "in" value if allocate=TRUE
1272
 
                                        and "out" when allocate=FALSE */
1273
 
        const char*     table_name,     /*!< in: table name */
1274
 
        mem_heap_t*     heap,           /*!< in/out: temporary memory heap */
1275
 
        const rec_t*    rec,            /*!< in: SYS_INDEXES record */
1276
 
        ibool           allocate,       /*!< in: TRUE=allocate *index,
1277
 
                                        FALSE=fill in a pre-allocated
1278
 
                                        *index */
1279
 
        dict_index_t**  index)          /*!< out,own: index, or NULL */
1280
 
{
1281
 
        const byte*     field;
1282
 
        ulint           len;
1283
 
        ulint           name_len;
1284
 
        char*           name_buf;
1285
 
        index_id_t      id;
1286
 
        ulint           n_fields;
1287
 
        ulint           type;
1288
 
        ulint           space;
1289
 
 
1290
 
        if (allocate) {
1291
 
                /* If allocate=TRUE, no dict_index_t will
1292
 
                be supplied. Initialize "*index" to NULL */
1293
 
                *index = NULL;
1294
 
        }
1295
 
 
1296
 
        if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
1297
 
                return(dict_load_index_del);
1298
 
        }
1299
 
 
1300
 
        if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 9)) {
1301
 
                return("wrong number of columns in SYS_INDEXES record");
1302
 
        }
1303
 
 
1304
 
        field = rec_get_nth_field_old(rec, 0/*TABLE_ID*/, &len);
1305
 
        if (UNIV_UNLIKELY(len != 8)) {
1306
 
err_len:
1307
 
                return("incorrect column length in SYS_INDEXES");
1308
 
        }
1309
 
 
1310
 
        if (!allocate) {
1311
 
                /* We are reading a SYS_INDEXES record. Copy the table_id */
1312
 
                memcpy(table_id, (const char*)field, 8);
1313
 
        } else if (memcmp(field, table_id, 8)) {
1314
 
                /* Caller supplied table_id, verify it is the same
1315
 
                id as on the index record */
1316
 
                return(dict_load_index_id_err);
1317
 
        }
1318
 
 
1319
 
        field = rec_get_nth_field_old(rec, 1/*ID*/, &len);
1320
 
        if (UNIV_UNLIKELY(len != 8)) {
1321
 
                goto err_len;
1322
 
        }
1323
 
 
1324
 
        id = mach_read_from_8(field);
1325
 
 
1326
 
        rec_get_nth_field_offs_old(rec, 2/*DB_TRX_ID*/, &len);
1327
 
        if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
1328
 
                goto err_len;
1329
 
        }
1330
 
        rec_get_nth_field_offs_old(rec, 3/*DB_ROLL_PTR*/, &len);
1331
 
        if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
1332
 
                goto err_len;
1333
 
        }
1334
 
 
1335
 
        field = rec_get_nth_field_old(rec, 4/*NAME*/, &name_len);
1336
 
        if (UNIV_UNLIKELY(name_len == UNIV_SQL_NULL)) {
1337
 
                goto err_len;
1338
 
        }
1339
 
 
1340
 
        name_buf = mem_heap_strdupl(heap, (const char*) field,
1341
 
                                    name_len);
1342
 
 
1343
 
        field = rec_get_nth_field_old(rec, 5/*N_FIELDS*/, &len);
1344
 
        if (UNIV_UNLIKELY(len != 4)) {
1345
 
                goto err_len;
1346
 
        }
1347
 
        n_fields = mach_read_from_4(field);
1348
 
 
1349
 
        field = rec_get_nth_field_old(rec, 6/*TYPE*/, &len);
1350
 
        if (UNIV_UNLIKELY(len != 4)) {
1351
 
                goto err_len;
1352
 
        }
1353
 
        type = mach_read_from_4(field);
1354
 
 
1355
 
        field = rec_get_nth_field_old(rec, 7/*SPACE*/, &len);
1356
 
        if (UNIV_UNLIKELY(len != 4)) {
1357
 
                goto err_len;
1358
 
        }
1359
 
        space = mach_read_from_4(field);
1360
 
 
1361
 
        field = rec_get_nth_field_old(rec, 8/*PAGE_NO*/, &len);
1362
 
        if (UNIV_UNLIKELY(len != 4)) {
1363
 
                goto err_len;
1364
 
        }
1365
 
 
1366
 
        if (allocate) {
1367
 
                *index = dict_mem_index_create(table_name, name_buf,
1368
 
                                               space, type, n_fields);
1369
 
        } else {
1370
 
                ut_a(*index);
1371
 
 
1372
 
                dict_mem_fill_index_struct(*index, NULL, NULL, name_buf,
1373
 
                                           space, type, n_fields);
1374
 
        }
1375
 
 
1376
 
        (*index)->id = id;
1377
 
        (*index)->page = mach_read_from_4(field);
1378
 
        ut_ad((*index)->page);
1379
 
 
1380
 
        return(NULL);
1381
707
}
1382
708
 
1383
709
/********************************************************************//**
1389
715
ulint
1390
716
dict_load_indexes(
1391
717
/*==============*/
1392
 
        dict_table_t*   table,  /*!< in/out: table */
 
718
        dict_table_t*   table,  /*!< in: table */
1393
719
        mem_heap_t*     heap)   /*!< in: memory heap for temporary storage */
1394
720
{
1395
721
        dict_table_t*   sys_indexes;
1396
722
        dict_index_t*   sys_index;
 
723
        dict_index_t*   index;
1397
724
        btr_pcur_t      pcur;
1398
725
        dtuple_t*       tuple;
1399
726
        dfield_t*       dfield;
1400
727
        const rec_t*    rec;
 
728
        const byte*     field;
 
729
        ulint           len;
 
730
        ulint           name_len;
 
731
        char*           name_buf;
 
732
        ulint           type;
 
733
        ulint           space;
 
734
        ulint           page_no;
 
735
        ulint           n_fields;
1401
736
        byte*           buf;
 
737
        ibool           is_sys_table;
 
738
        dulint          id;
1402
739
        mtr_t           mtr;
1403
740
        ulint           error = DB_SUCCESS;
1404
741
 
1405
742
        ut_ad(mutex_own(&(dict_sys->mutex)));
1406
743
 
 
744
        if ((ut_dulint_get_high(table->id) == 0)
 
745
            && (ut_dulint_get_low(table->id) < DICT_HDR_FIRST_ID)) {
 
746
                is_sys_table = TRUE;
 
747
        } else {
 
748
                is_sys_table = FALSE;
 
749
        }
 
750
 
1407
751
        mtr_start(&mtr);
1408
752
 
1409
753
        sys_indexes = dict_table_get_low("SYS_INDEXES");
1410
754
        sys_index = UT_LIST_GET_FIRST(sys_indexes->indexes);
1411
755
        ut_a(!dict_table_is_comp(sys_indexes));
1412
 
        ut_a(name_of_col_is(sys_indexes, sys_index, 4, "NAME"));
1413
 
        ut_a(name_of_col_is(sys_indexes, sys_index, 8, "PAGE_NO"));
1414
756
 
1415
757
        tuple = dtuple_create(heap, 1);
1416
758
        dfield = dtuple_get_nth_field(tuple, 0);
1417
759
 
1418
 
        buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
 
760
        buf = mem_heap_alloc(heap, 8);
1419
761
        mach_write_to_8(buf, table->id);
1420
762
 
1421
763
        dfield_set_data(dfield, buf, 8);
1424
766
        btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
1425
767
                                  BTR_SEARCH_LEAF, &pcur, &mtr);
1426
768
        for (;;) {
1427
 
                dict_index_t*   index = NULL;
1428
 
                const char*     err_msg;
1429
 
 
1430
769
                if (!btr_pcur_is_on_user_rec(&pcur)) {
1431
770
 
1432
771
                        break;
1434
773
 
1435
774
                rec = btr_pcur_get_rec(&pcur);
1436
775
 
1437
 
                err_msg = dict_load_index_low(buf, table->name, heap, rec,
1438
 
                                              TRUE, &index);
1439
 
                ut_ad((index == NULL) == (err_msg != NULL));
 
776
                field = rec_get_nth_field_old(rec, 0, &len);
 
777
                ut_ad(len == 8);
1440
778
 
1441
 
                if (err_msg == dict_load_index_id_err) {
1442
 
                        /* TABLE_ID mismatch means that we have
1443
 
                        run out of index definitions for the table. */
 
779
                if (ut_memcmp(buf, field, len) != 0) {
1444
780
                        break;
1445
 
                } else if (err_msg == dict_load_index_del) {
1446
 
                        /* Skip delete-marked records. */
 
781
                } else if (rec_get_deleted_flag(rec, 0)) {
 
782
                        /* Skip delete marked records */
1447
783
                        goto next_rec;
1448
 
                } else if (err_msg) {
1449
 
                        fprintf(stderr, "InnoDB: %s\n", err_msg);
1450
 
                        error = DB_CORRUPTION;
1451
 
                        goto func_exit;
1452
784
                }
1453
785
 
1454
 
                ut_ad(index);
 
786
                field = rec_get_nth_field_old(rec, 1, &len);
 
787
                ut_ad(len == 8);
 
788
                id = mach_read_from_8(field);
 
789
 
 
790
                ut_a(name_of_col_is(sys_indexes, sys_index, 4, "NAME"));
 
791
 
 
792
                field = rec_get_nth_field_old(rec, 4, &name_len);
 
793
                name_buf = mem_heap_strdupl(heap, (char*) field, name_len);
 
794
 
 
795
                field = rec_get_nth_field_old(rec, 5, &len);
 
796
                n_fields = mach_read_from_4(field);
 
797
 
 
798
                field = rec_get_nth_field_old(rec, 6, &len);
 
799
                type = mach_read_from_4(field);
 
800
 
 
801
                field = rec_get_nth_field_old(rec, 7, &len);
 
802
                space = mach_read_from_4(field);
 
803
 
 
804
                ut_a(name_of_col_is(sys_indexes, sys_index, 8, "PAGE_NO"));
 
805
 
 
806
                field = rec_get_nth_field_old(rec, 8, &len);
 
807
                page_no = mach_read_from_4(field);
1455
808
 
1456
809
                /* We check for unsupported types first, so that the
1457
810
                subsequent checks are relevant for the supported types. */
1458
 
                if (index->type & ~(DICT_CLUSTERED | DICT_UNIQUE)) {
 
811
                if (type & ~(DICT_CLUSTERED | DICT_UNIQUE)) {
1459
812
 
1460
813
                        fprintf(stderr,
1461
814
                                "InnoDB: Error: unknown type %lu"
1462
815
                                " of index %s of table %s\n",
1463
 
                                (ulong) index->type, index->name, table->name);
 
816
                                (ulong) type, name_buf, table->name);
1464
817
 
1465
818
                        error = DB_UNSUPPORTED;
1466
 
                        dict_mem_index_free(index);
1467
819
                        goto func_exit;
1468
 
                } else if (index->page == FIL_NULL) {
 
820
                } else if (page_no == FIL_NULL) {
1469
821
 
1470
822
                        fprintf(stderr,
1471
823
                                "InnoDB: Error: trying to load index %s"
1472
824
                                " for table %s\n"
1473
825
                                "InnoDB: but the index tree has been freed!\n",
1474
 
                                index->name, table->name);
 
826
                                name_buf, table->name);
1475
827
 
1476
 
corrupted:
1477
 
                        dict_mem_index_free(index);
1478
828
                        error = DB_CORRUPTION;
1479
829
                        goto func_exit;
1480
 
                } else if (!dict_index_is_clust(index)
1481
 
                           && NULL == dict_table_get_first_index(table)) {
 
830
                } else if ((type & DICT_CLUSTERED) == 0
 
831
                            && NULL == dict_table_get_first_index(table)) {
1482
832
 
1483
833
                        fputs("InnoDB: Error: trying to load index ",
1484
834
                              stderr);
1485
 
                        ut_print_name(stderr, NULL, FALSE, index->name);
 
835
                        ut_print_name(stderr, NULL, FALSE, name_buf);
1486
836
                        fputs(" for table ", stderr);
1487
837
                        ut_print_name(stderr, NULL, TRUE, table->name);
1488
838
                        fputs("\nInnoDB: but the first index"
1489
839
                              " is not clustered!\n", stderr);
1490
840
 
1491
 
                        goto corrupted;
1492
 
                } else if (table->id < DICT_HDR_FIRST_ID
1493
 
                           && (dict_index_is_clust(index)
 
841
                        error = DB_CORRUPTION;
 
842
                        goto func_exit;
 
843
                } else if (is_sys_table
 
844
                           && ((type & DICT_CLUSTERED)
1494
845
                               || ((table == dict_sys->sys_tables)
1495
 
                                   && !strcmp("ID_IND", index->name)))) {
 
846
                                   && (name_len == (sizeof "ID_IND") - 1)
 
847
                                   && (0 == ut_memcmp(name_buf,
 
848
                                                      "ID_IND", name_len))))) {
1496
849
 
1497
850
                        /* The index was created in memory already at booting
1498
851
                        of the database server */
1499
 
                        dict_mem_index_free(index);
1500
852
                } else {
 
853
                        index = dict_mem_index_create(table->name, name_buf,
 
854
                                                      space, type, n_fields);
 
855
                        index->id = id;
 
856
 
1501
857
                        dict_load_fields(index, heap);
1502
 
                        error = dict_index_add_to_cache(table, index,
1503
 
                                                        index->page, FALSE);
 
858
                        error = dict_index_add_to_cache(table, index, page_no,
 
859
                                                        FALSE);
1504
860
                        /* The data dictionary tables should never contain
1505
861
                        invalid index definitions.  If we ignored this error
1506
862
                        and simply did not load this index definition, the
1524
880
}
1525
881
 
1526
882
/********************************************************************//**
1527
 
Loads a table definition from a SYS_TABLES record to dict_table_t.
1528
 
Does not load any columns or indexes.
1529
 
@return error message, or NULL on success */
1530
 
UNIV_INTERN
1531
 
const char*
1532
 
dict_load_table_low(
1533
 
/*================*/
1534
 
        const char*     name,           /*!< in: table name */
1535
 
        const rec_t*    rec,            /*!< in: SYS_TABLES record */
1536
 
        dict_table_t**  table)          /*!< out,own: table, or NULL */
1537
 
{
1538
 
        const byte*     field;
1539
 
        ulint           len;
1540
 
        ulint           space;
1541
 
        ulint           n_cols;
1542
 
        ulint           flags;
1543
 
 
1544
 
        if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
1545
 
                return("delete-marked record in SYS_TABLES");
1546
 
        }
1547
 
 
1548
 
        if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 10)) {
1549
 
                return("wrong number of columns in SYS_TABLES record");
1550
 
        }
1551
 
 
1552
 
        rec_get_nth_field_offs_old(rec, 0/*NAME*/, &len);
1553
 
        if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
1554
 
err_len:
1555
 
                return("incorrect column length in SYS_TABLES");
1556
 
        }
1557
 
        rec_get_nth_field_offs_old(rec, 1/*DB_TRX_ID*/, &len);
1558
 
        if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
1559
 
                goto err_len;
1560
 
        }
1561
 
        rec_get_nth_field_offs_old(rec, 2/*DB_ROLL_PTR*/, &len);
1562
 
        if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
1563
 
                goto err_len;
1564
 
        }
1565
 
 
1566
 
        rec_get_nth_field_offs_old(rec, 3/*ID*/, &len);
1567
 
        if (UNIV_UNLIKELY(len != 8)) {
1568
 
                goto err_len;
1569
 
        }
1570
 
 
1571
 
        field = rec_get_nth_field_old(rec, 4/*N_COLS*/, &len);
1572
 
        if (UNIV_UNLIKELY(len != 4)) {
1573
 
                goto err_len;
1574
 
        }
1575
 
 
1576
 
        n_cols = mach_read_from_4(field);
1577
 
 
1578
 
        rec_get_nth_field_offs_old(rec, 5/*TYPE*/, &len);
1579
 
        if (UNIV_UNLIKELY(len != 4)) {
1580
 
                goto err_len;
1581
 
        }
1582
 
 
1583
 
        rec_get_nth_field_offs_old(rec, 6/*MIX_ID*/, &len);
1584
 
        if (UNIV_UNLIKELY(len != 8)) {
1585
 
                goto err_len;
1586
 
        }
1587
 
 
1588
 
        rec_get_nth_field_offs_old(rec, 7/*MIX_LEN*/, &len);
1589
 
        if (UNIV_UNLIKELY(len != 4)) {
1590
 
                goto err_len;
1591
 
        }
1592
 
 
1593
 
        rec_get_nth_field_offs_old(rec, 8/*CLUSTER_ID*/, &len);
1594
 
        if (UNIV_UNLIKELY(len != UNIV_SQL_NULL)) {
1595
 
                goto err_len;
1596
 
        }
1597
 
 
1598
 
        field = rec_get_nth_field_old(rec, 9/*SPACE*/, &len);
1599
 
 
1600
 
        if (UNIV_UNLIKELY(len != 4)) {
1601
 
                goto err_len;
1602
 
        }
1603
 
 
1604
 
        space = mach_read_from_4(field);
1605
 
 
1606
 
        /* Check if the tablespace exists and has the right name */
1607
 
        if (space != 0) {
1608
 
                flags = dict_sys_tables_get_flags(rec);
1609
 
 
1610
 
                if (UNIV_UNLIKELY(flags == ULINT_UNDEFINED)) {
1611
 
                        field = rec_get_nth_field_old(rec, 5/*TYPE*/, &len);
1612
 
                        ut_ad(len == 4); /* this was checked earlier */
1613
 
                        flags = mach_read_from_4(field);
1614
 
 
1615
 
                        ut_print_timestamp(stderr);
1616
 
                        fputs("  InnoDB: Error: table ", stderr);
1617
 
                        ut_print_filename(stderr, name);
1618
 
                        fprintf(stderr, "\n"
1619
 
                                "InnoDB: in InnoDB data dictionary"
1620
 
                                " has unknown type %lx.\n",
1621
 
                                (ulong) flags);
1622
 
                        return(NULL);
1623
 
                }
1624
 
        } else {
1625
 
                flags = 0;
1626
 
        }
1627
 
 
1628
 
        /* The high-order bit of N_COLS is the "compact format" flag.
1629
 
        For tables in that format, MIX_LEN may hold additional flags. */
1630
 
        if (n_cols & 0x80000000UL) {
1631
 
                ulint   flags2;
1632
 
 
1633
 
                flags |= DICT_TF_COMPACT;
1634
 
 
1635
 
                field = rec_get_nth_field_old(rec, 7, &len);
1636
 
 
1637
 
                if (UNIV_UNLIKELY(len != 4)) {
1638
 
 
1639
 
                        goto err_len;
1640
 
                }
1641
 
 
1642
 
                flags2 = mach_read_from_4(field);
1643
 
 
1644
 
                if (flags2 & (SIZE_MAX << (DICT_TF2_BITS - DICT_TF2_SHIFT))) {
1645
 
                        ut_print_timestamp(stderr);
1646
 
                        fputs("  InnoDB: Warning: table ", stderr);
1647
 
                        ut_print_filename(stderr, name);
1648
 
                        fprintf(stderr, "\n"
1649
 
                                "InnoDB: in InnoDB data dictionary"
1650
 
                                " has unknown flags %lx.\n",
1651
 
                                (ulong) flags2);
1652
 
 
1653
 
                        flags2 &= ~(~0 << (DICT_TF2_BITS - DICT_TF2_SHIFT));
1654
 
                }
1655
 
 
1656
 
                flags |= flags2 << DICT_TF2_SHIFT;
1657
 
        }
1658
 
 
1659
 
        /* See if the tablespace is available. */
1660
 
        *table = dict_mem_table_create(name, space, n_cols & ~0x80000000UL,
1661
 
                                       flags);
1662
 
 
1663
 
        field = rec_get_nth_field_old(rec, 3/*ID*/, &len);
1664
 
        ut_ad(len == 8); /* this was checked earlier */
1665
 
 
1666
 
        (*table)->id = mach_read_from_8(field);
1667
 
 
1668
 
        (*table)->ibd_file_missing = FALSE;
1669
 
 
1670
 
        return(NULL);
1671
 
}
1672
 
 
1673
 
/********************************************************************//**
1674
883
Loads a table definition and also all its index definitions, and also
1675
884
the cluster definition if the table is a member in a cluster. Also loads
1676
885
all foreign key constraints where the foreign key is in the table or where
1683
892
dict_table_t*
1684
893
dict_load_table(
1685
894
/*============*/
1686
 
        const char*     name,   /*!< in: table name in the
 
895
        const char*     name)   /*!< in: table name in the
1687
896
                                databasename/tablename format */
1688
 
        ibool           cached) /*!< in: TRUE=add to cache, FALSE=do not */
1689
897
{
 
898
        ibool           ibd_file_missing        = FALSE;
1690
899
        dict_table_t*   table;
1691
900
        dict_table_t*   sys_tables;
1692
901
        btr_pcur_t      pcur;
1697
906
        const rec_t*    rec;
1698
907
        const byte*     field;
1699
908
        ulint           len;
 
909
        ulint           space;
 
910
        ulint           n_cols;
 
911
        ulint           flags;
1700
912
        ulint           err;
1701
 
        const char*     err_msg;
1702
913
        mtr_t           mtr;
1703
914
 
1704
915
        ut_ad(mutex_own(&(dict_sys->mutex)));
1710
921
        sys_tables = dict_table_get_low("SYS_TABLES");
1711
922
        sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
1712
923
        ut_a(!dict_table_is_comp(sys_tables));
1713
 
        ut_a(name_of_col_is(sys_tables, sys_index, 3, "ID"));
1714
 
        ut_a(name_of_col_is(sys_tables, sys_index, 4, "N_COLS"));
1715
 
        ut_a(name_of_col_is(sys_tables, sys_index, 5, "TYPE"));
1716
 
        ut_a(name_of_col_is(sys_tables, sys_index, 7, "MIX_LEN"));
1717
 
        ut_a(name_of_col_is(sys_tables, sys_index, 9, "SPACE"));
1718
924
 
1719
925
        tuple = dtuple_create(heap, 1);
1720
926
        dfield = dtuple_get_nth_field(tuple, 0);
1745
951
                goto err_exit;
1746
952
        }
1747
953
 
1748
 
        err_msg = dict_load_table_low(name, rec, &table);
1749
 
 
1750
 
        if (err_msg) {
1751
 
 
1752
 
                ut_print_timestamp(stderr);
1753
 
                fprintf(stderr, "  InnoDB: %s\n", err_msg);
1754
 
                goto err_exit;
1755
 
        }
1756
 
 
1757
 
        if (table->space == 0) {
1758
 
                /* The system tablespace is always available. */
1759
 
        } else if (!fil_space_for_table_exists_in_mem(
1760
 
                           table->space, name,
1761
 
                           (table->flags >> DICT_TF2_SHIFT)
1762
 
                           & DICT_TF2_TEMPORARY,
1763
 
                           FALSE, FALSE)) {
1764
 
 
1765
 
                if (table->flags & (DICT_TF2_TEMPORARY << DICT_TF2_SHIFT)) {
1766
 
                        /* Do not bother to retry opening temporary tables. */
1767
 
                        table->ibd_file_missing = TRUE;
 
954
        ut_a(name_of_col_is(sys_tables, sys_index, 9, "SPACE"));
 
955
 
 
956
        field = rec_get_nth_field_old(rec, 9, &len);
 
957
        space = mach_read_from_4(field);
 
958
 
 
959
        /* Check if the tablespace exists and has the right name */
 
960
        if (space != 0) {
 
961
                flags = dict_sys_tables_get_flags(rec);
 
962
 
 
963
                if (UNIV_UNLIKELY(flags == ULINT_UNDEFINED)) {
 
964
                        field = rec_get_nth_field_old(rec, 5, &len);
 
965
                        flags = mach_read_from_4(field);
 
966
 
 
967
                        ut_print_timestamp(stderr);
 
968
                        fputs("  InnoDB: Error: table ", stderr);
 
969
                        ut_print_filename(stderr, name);
 
970
                        fprintf(stderr, "\n"
 
971
                                "InnoDB: in InnoDB data dictionary"
 
972
                                " has unknown type %lx.\n",
 
973
                                (ulong) flags);
 
974
                        goto err_exit;
 
975
                }
 
976
 
 
977
                if (fil_space_for_table_exists_in_mem(space, name, FALSE,
 
978
                                                      FALSE, FALSE)) {
 
979
                        /* Ok; (if we did a crash recovery then the tablespace
 
980
                        can already be in the memory cache) */
1768
981
                } else {
 
982
                        /* In >= 4.1.9, InnoDB scans the data dictionary also
 
983
                        at a normal mysqld startup. It is an error if the
 
984
                        space object does not exist in memory. */
 
985
 
1769
986
                        ut_print_timestamp(stderr);
1770
987
                        fprintf(stderr,
1771
 
                                "  InnoDB: error: space object of table ");
1772
 
                        ut_print_filename(stderr, name);
1773
 
                        fprintf(stderr, ",\n"
 
988
                                "  InnoDB: error: space object of table %s,\n"
1774
989
                                "InnoDB: space id %lu did not exist in memory."
1775
990
                                " Retrying an open.\n",
1776
 
                                (ulong) table->space);
 
991
                                name, (ulong)space);
1777
992
                        /* Try to open the tablespace */
1778
993
                        if (!fil_open_single_table_tablespace(
1779
 
                                TRUE, table->space,
1780
 
                                table->flags == DICT_TF_COMPACT ? 0 :
1781
 
                                table->flags & ~(~0 << DICT_TF_BITS), name)) {
1782
 
                                /* We failed to find a sensible
1783
 
                                tablespace file */
 
994
                                    TRUE, space, flags, name)) {
 
995
                                /* We failed to find a sensible tablespace
 
996
                                file */
1784
997
 
1785
 
                                table->ibd_file_missing = TRUE;
 
998
                                ibd_file_missing = TRUE;
1786
999
                        }
1787
1000
                }
1788
 
        }
 
1001
        } else {
 
1002
                flags = 0;
 
1003
        }
 
1004
 
 
1005
        ut_a(name_of_col_is(sys_tables, sys_index, 4, "N_COLS"));
 
1006
 
 
1007
        field = rec_get_nth_field_old(rec, 4, &len);
 
1008
        n_cols = mach_read_from_4(field);
 
1009
 
 
1010
        /* The high-order bit of N_COLS is the "compact format" flag. */
 
1011
        if (n_cols & 0x80000000UL) {
 
1012
                flags |= DICT_TF_COMPACT;
 
1013
        }
 
1014
 
 
1015
        table = dict_mem_table_create(name, space, n_cols & ~0x80000000UL,
 
1016
                                      flags);
 
1017
 
 
1018
        table->ibd_file_missing = (unsigned int) ibd_file_missing;
 
1019
 
 
1020
        ut_a(name_of_col_is(sys_tables, sys_index, 3, "ID"));
 
1021
 
 
1022
        field = rec_get_nth_field_old(rec, 3, &len);
 
1023
        table->id = mach_read_from_8(field);
1789
1024
 
1790
1025
        btr_pcur_close(&pcur);
1791
1026
        mtr_commit(&mtr);
1792
1027
 
1793
1028
        dict_load_columns(table, heap);
1794
1029
 
1795
 
        if (cached) {
1796
 
                dict_table_add_to_cache(table, heap);
1797
 
        } else {
1798
 
                dict_table_add_system_columns(table, heap);
1799
 
        }
 
1030
        dict_table_add_to_cache(table, heap);
1800
1031
 
1801
1032
        mem_heap_empty(heap);
1802
1033
 
1803
1034
        err = dict_load_indexes(table, heap);
1804
1035
 
1805
 
        /* Initialize table foreign_child value. Its value could be
1806
 
        changed when dict_load_foreigns() is called below */
1807
 
        table->fk_max_recusive_level = 0;
1808
 
 
1809
1036
        /* If the force recovery flag is set, we open the table irrespective
1810
1037
        of the error condition, since the user may want to dump data from the
1811
1038
        clustered index. However we load the foreign key information only if
1812
1039
        all indexes were loaded. */
1813
 
        if (!cached) {
1814
 
        } else if (err == DB_SUCCESS) {
1815
 
                err = dict_load_foreigns(table->name, TRUE, TRUE);
1816
 
 
1817
 
                if (err != DB_SUCCESS) {
1818
 
                        dict_table_remove_from_cache(table);
1819
 
                        table = NULL;
1820
 
                } else {
1821
 
                        table->fk_max_recusive_level = 0;
1822
 
                }
 
1040
        if (err == DB_SUCCESS) {
 
1041
                err = dict_load_foreigns(table->name, TRUE);
1823
1042
        } else if (!srv_force_recovery) {
1824
1043
                dict_table_remove_from_cache(table);
1825
1044
                table = NULL;
1860
1079
dict_table_t*
1861
1080
dict_load_table_on_id(
1862
1081
/*==================*/
1863
 
        table_id_t      table_id)       /*!< in: table id */
 
1082
        dulint  table_id)       /*!< in: table id */
1864
1083
{
1865
1084
        byte            id_buf[8];
1866
1085
        btr_pcur_t      pcur;
1877
1096
 
1878
1097
        ut_ad(mutex_own(&(dict_sys->mutex)));
1879
1098
 
1880
 
        table = NULL;
1881
 
 
1882
1099
        /* NOTE that the operation of this function is protected by
1883
1100
        the dictionary mutex, and therefore no deadlocks can occur
1884
1101
        with other dictionary operations. */
1905
1122
                                  BTR_SEARCH_LEAF, &pcur, &mtr);
1906
1123
        rec = btr_pcur_get_rec(&pcur);
1907
1124
 
1908
 
        if (!btr_pcur_is_on_user_rec(&pcur)) {
 
1125
        if (!btr_pcur_is_on_user_rec(&pcur)
 
1126
            || rec_get_deleted_flag(rec, 0)) {
1909
1127
                /* Not found */
1910
 
                goto func_exit;
1911
 
        }
1912
 
 
1913
 
        /* Find the first record that is not delete marked */
1914
 
        while (rec_get_deleted_flag(rec, 0)) {
1915
 
                if (!btr_pcur_move_to_next_user_rec(&pcur, &mtr)) {
1916
 
                        goto func_exit;
1917
 
                }
1918
 
                rec = btr_pcur_get_rec(&pcur);
 
1128
 
 
1129
                btr_pcur_close(&pcur);
 
1130
                mtr_commit(&mtr);
 
1131
                mem_heap_free(heap);
 
1132
 
 
1133
                return(NULL);
1919
1134
        }
1920
1135
 
1921
1136
        /*---------------------------------------------------*/
1927
1142
        ut_ad(len == 8);
1928
1143
 
1929
1144
        /* Check if the table id in record is the one searched for */
1930
 
        if (table_id != mach_read_from_8(field)) {
1931
 
                goto func_exit;
 
1145
        if (ut_dulint_cmp(table_id, mach_read_from_8(field)) != 0) {
 
1146
 
 
1147
                btr_pcur_close(&pcur);
 
1148
                mtr_commit(&mtr);
 
1149
                mem_heap_free(heap);
 
1150
 
 
1151
                return(NULL);
1932
1152
        }
1933
1153
 
1934
1154
        /* Now we get the table name from the record */
1935
1155
        field = rec_get_nth_field_old(rec, 1, &len);
1936
1156
        /* Load the table definition to memory */
1937
 
        table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len),
1938
 
                                TRUE);
1939
 
func_exit:
 
1157
        table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len));
 
1158
 
1940
1159
        btr_pcur_close(&pcur);
1941
1160
        mtr_commit(&mtr);
1942
1161
        mem_heap_free(heap);
1988
1207
 
1989
1208
        ut_ad(mutex_own(&(dict_sys->mutex)));
1990
1209
 
1991
 
        foreign->foreign_col_names = static_cast<const char **>(mem_heap_alloc(
1992
 
                foreign->heap, foreign->n_fields * sizeof(void*)));
 
1210
        foreign->foreign_col_names = mem_heap_alloc(
 
1211
                foreign->heap, foreign->n_fields * sizeof(void*));
1993
1212
 
1994
 
        foreign->referenced_col_names = static_cast<const char **>(mem_heap_alloc(
1995
 
                foreign->heap, foreign->n_fields * sizeof(void*)));
 
1213
        foreign->referenced_col_names = mem_heap_alloc(
 
1214
                foreign->heap, foreign->n_fields * sizeof(void*));
1996
1215
        mtr_start(&mtr);
1997
1216
 
1998
1217
        sys_foreign_cols = dict_table_get_low("SYS_FOREIGN_COLS");
2046
1265
/*==============*/
2047
1266
        const char*     id,     /*!< in: foreign constraint id as a
2048
1267
                                null-terminated string */
2049
 
        ibool           check_charsets,
 
1268
        ibool           check_charsets)
2050
1269
                                /*!< in: TRUE=check charset compatibility */
2051
 
        ibool           check_recursive)
2052
 
                                /*!< in: Whether to record the foreign table
2053
 
                                parent count to avoid unlimited recursive
2054
 
                                load of chained foreign tables */
2055
1270
{
2056
1271
        dict_foreign_t* foreign;
2057
1272
        dict_table_t*   sys_foreign;
2065
1280
        ulint           len;
2066
1281
        ulint           n_fields_and_type;
2067
1282
        mtr_t           mtr;
2068
 
        dict_table_t*   for_table;
2069
 
        dict_table_t*   ref_table;
2070
1283
 
2071
1284
        ut_ad(mutex_own(&(dict_sys->mutex)));
2072
1285
 
2151
1364
 
2152
1365
        dict_load_foreign_cols(id, foreign);
2153
1366
 
2154
 
        ref_table = dict_table_check_if_in_cache_low(
2155
 
                        foreign->referenced_table_name);
2156
 
 
2157
 
        /* We could possibly wind up in a deep recursive calls if
2158
 
        we call dict_table_get_low() again here if there
2159
 
        is a chain of tables concatenated together with
2160
 
        foreign constraints. In such case, each table is
2161
 
        both a parent and child of the other tables, and
2162
 
        act as a "link" in such table chains.
2163
 
        To avoid such scenario, we would need to check the
2164
 
        number of ancesters the current table has. If that
2165
 
        exceeds DICT_FK_MAX_CHAIN_LEN, we will stop loading
2166
 
        the child table.
2167
 
        Foreign constraints are loaded in a Breath First fashion,
2168
 
        that is, the index on FOR_NAME is scanned first, and then
2169
 
        index on REF_NAME. So foreign constrains in which
2170
 
        current table is a child (foreign table) are loaded first,
2171
 
        and then those constraints where current table is a
2172
 
        parent (referenced) table.
2173
 
        Thus we could check the parent (ref_table) table's
2174
 
        reference count (fk_max_recusive_level) to know how deep the
2175
 
        recursive call is. If the parent table (ref_table) is already
2176
 
        loaded, and its fk_max_recusive_level is larger than
2177
 
        DICT_FK_MAX_CHAIN_LEN, we will stop the recursive loading
2178
 
        by skipping loading the child table. It will not affect foreign
2179
 
        constraint check for DMLs since child table will be loaded
2180
 
        at that time for the constraint check. */
2181
 
        if (!ref_table
2182
 
            || ref_table->fk_max_recusive_level < DICT_FK_MAX_RECURSIVE_LOAD) {
2183
 
 
2184
 
                /* If the foreign table is not yet in the dictionary cache, we
2185
 
                have to load it so that we are able to make type comparisons
2186
 
                in the next function call. */
2187
 
 
2188
 
                for_table = dict_table_get_low(foreign->foreign_table_name);
2189
 
 
2190
 
                if (for_table && ref_table && check_recursive) {
2191
 
                        /* This is to record the longest chain of ancesters
2192
 
                        this table has, if the parent has more ancesters
2193
 
                        than this table has, record it after add 1 (for this
2194
 
                        parent */
2195
 
                        if (ref_table->fk_max_recusive_level
2196
 
                            >= for_table->fk_max_recusive_level) {
2197
 
                                for_table->fk_max_recusive_level =
2198
 
                                         ref_table->fk_max_recusive_level + 1;
2199
 
                        }
2200
 
                }
2201
 
        }
 
1367
        /* If the foreign table is not yet in the dictionary cache, we
 
1368
        have to load it so that we are able to make type comparisons
 
1369
        in the next function call. */
 
1370
 
 
1371
        dict_table_get_low(foreign->foreign_table_name);
2202
1372
 
2203
1373
        /* Note that there may already be a foreign constraint object in
2204
1374
        the dictionary cache for this constraint: then the following
2223
1393
dict_load_foreigns(
2224
1394
/*===============*/
2225
1395
        const char*     table_name,     /*!< in: table name */
2226
 
        ibool           check_recursive,/*!< in: Whether to check recursive
2227
 
                                        load of tables chained by FK */
2228
1396
        ibool           check_charsets) /*!< in: TRUE=check charset
2229
1397
                                        compatibility */
2230
1398
{
2295
1463
 
2296
1464
        if (0 != cmp_data_data(dfield_get_type(dfield)->mtype,
2297
1465
                               dfield_get_type(dfield)->prtype,
2298
 
                               static_cast<const unsigned char *>(dfield_get_data(dfield)),
2299
 
                               dfield_get_len(dfield),
 
1466
                               dfield_get_data(dfield), dfield_get_len(dfield),
2300
1467
                               field, len)) {
2301
1468
 
2302
1469
                goto load_next_index;
2327
1494
 
2328
1495
        /* Load the foreign constraint definition to the dictionary cache */
2329
1496
 
2330
 
        err = dict_load_foreign(id, check_charsets, check_recursive);
 
1497
        err = dict_load_foreign(id, check_charsets);
2331
1498
 
2332
1499
        if (err != DB_SUCCESS) {
2333
1500
                btr_pcur_close(&pcur);
2355
1522
 
2356
1523
                mtr_start(&mtr);
2357
1524
 
2358
 
                /* Switch to scan index on REF_NAME, fk_max_recusive_level
2359
 
                already been updated when scanning FOR_NAME index, no need to
2360
 
                update again */
2361
 
                check_recursive = FALSE;
2362
 
 
2363
1525
                goto start_load;
2364
1526
        }
2365
1527