~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2009-11-24 02:06:37 UTC
  • mfrom: (1223.1.7 push)
  • Revision ID: brian@gaz-20091124020637-9gb65vj98x1arydm
MergeĀ forĀ staging.

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
 
24
24
Created 4/24/1996 Heikki Tuuri
25
25
*******************************************************/
26
26
 
 
27
#include "dict0load.h"
27
28
#if defined(BUILD_DRIZZLE)
28
 
# include "config.h"
 
29
# include "drizzled/global.h"
29
30
#else
30
31
# include "mysql_version.h"
31
32
#endif /* BUILD_DRIZZLE */
32
 
#include "dict0load.h"
33
33
 
34
34
#ifdef UNIV_NONINL
35
35
#include "dict0load.ic"
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
{
168
 
        dict_table_t*   table;
169
 
        btr_pcur_t      pcur;
170
 
        const rec_t*    rec;
171
 
        mem_heap_t*     heap;
172
 
        mtr_t           mtr;
173
 
 
174
 
        /* Enlarge the fatal semaphore wait timeout during the InnoDB table
175
 
        monitor printout */
176
 
 
177
 
        mutex_enter(&kernel_mutex);
178
 
        srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
179
 
        mutex_exit(&kernel_mutex);
180
 
 
181
 
        heap = mem_heap_create(1000);
182
 
        mutex_enter(&(dict_sys->mutex));
183
 
 
184
 
        mtr_start(&mtr);
185
 
 
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) {
199
 
                        dict_table_print_low(table);
200
 
                } else {
201
 
                        ut_print_timestamp(stderr);
202
 
                        fprintf(stderr, "  InnoDB: %s\n", err_msg);
203
 
                }
204
 
 
205
 
                mem_heap_empty(heap);
206
 
 
207
 
                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);
574
 
}
575
 
 
576
 
/*
577
 
  Send data to callback function .
578
 
*/
579
 
 
580
 
UNIV_INTERN void dict_print_with_callback(dict_print_callback func, void *func_arg)
581
 
{
582
158
        dict_table_t*   sys_tables;
583
159
        dict_index_t*   sys_index;
 
160
        dict_table_t*   table;
584
161
        btr_pcur_t      pcur;
585
162
        const rec_t*    rec;
586
163
        const byte*     field;
637
214
 
638
215
                mtr_commit(&mtr);
639
216
 
640
 
                func(func_arg, table_name);
 
217
                table = dict_table_get_low(table_name);
641
218
                mem_free(table_name);
642
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
 
 
232
                        dict_table_print_low(table);
 
233
                }
 
234
 
643
235
                mtr_start(&mtr);
644
236
 
645
237
                btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
672
264
                return(0);
673
265
        }
674
266
 
675
 
        field = rec_get_nth_field_old(rec, 4/*N_COLS*/, &len);
 
267
        field = rec_get_nth_field_old(rec, 4, &len);
676
268
        n_cols = mach_read_from_4(field);
677
269
 
678
270
        if (UNIV_UNLIKELY(!(n_cols & 0x80000000UL))) {
702
294
                return(ULINT_UNDEFINED);
703
295
        }
704
296
 
705
 
        if (UNIV_UNLIKELY(flags & (SIZE_MAX << DICT_TF_BITS))) {
 
297
        if (UNIV_UNLIKELY(flags & (~0 << DICT_TF_BITS))) {
706
298
                /* Some unused bits are set. */
707
299
                return(ULINT_UNDEFINED);
708
300
        }
728
320
        dict_index_t*   sys_index;
729
321
        btr_pcur_t      pcur;
730
322
        const rec_t*    rec;
731
 
        ulint           max_space_id;
 
323
        ulint           max_space_id    = 0;
732
324
        mtr_t           mtr;
733
325
 
734
326
        mutex_enter(&(dict_sys->mutex));
739
331
        sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
740
332
        ut_a(!dict_table_is_comp(sys_tables));
741
333
 
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
334
        btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
748
335
                                    TRUE, &mtr);
749
336
loop:
807
394
 
808
395
                mtr_commit(&mtr);
809
396
 
810
 
                if (space_id == 0) {
811
 
                        /* The system tablespace always exists. */
812
 
                } else if (in_crash_recovery) {
 
397
                if (space_id != 0 && in_crash_recovery) {
813
398
                        /* 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 {
 
399
                        exists; print a warning to the .err log if not */
 
400
 
 
401
                        fil_space_for_table_exists_in_mem(space_id, name,
 
402
                                                          FALSE, TRUE, TRUE);
 
403
                }
 
404
 
 
405
                if (space_id != 0 && !in_crash_recovery) {
839
406
                        /* It is a normal database startup: create the space
840
407
                        object and check that the .ibd file exists. */
841
408
 
858
425
}
859
426
 
860
427
/********************************************************************//**
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 */
 
428
Loads definitions for table columns. */
 
429
static
 
430
void
 
431
dict_load_columns(
 
432
/*==============*/
 
433
        dict_table_t*   table,  /*!< in: table */
 
434
        mem_heap_t*     heap)   /*!< in: memory heap for temporary storage */
879
435
{
 
436
        dict_table_t*   sys_columns;
 
437
        dict_index_t*   sys_index;
 
438
        btr_pcur_t      pcur;
 
439
        dtuple_t*       tuple;
 
440
        dfield_t*       dfield;
 
441
        const rec_t*    rec;
 
442
        const byte*     field;
 
443
        ulint           len;
 
444
        byte*           buf;
880
445
        char*           name;
881
 
        const byte*     field;
882
 
        ulint           len;
883
446
        ulint           mtype;
884
447
        ulint           prtype;
885
448
        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
449
        ulint           i;
1015
450
        mtr_t           mtr;
1016
451
 
1022
457
        sys_index = UT_LIST_GET_FIRST(sys_columns->indexes);
1023
458
        ut_a(!dict_table_is_comp(sys_columns));
1024
459
 
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
460
        tuple = dtuple_create(heap, 1);
1029
461
        dfield = dtuple_get_nth_field(tuple, 0);
1030
462
 
1031
 
        buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
 
463
        buf = mem_heap_alloc(heap, 8);
1032
464
        mach_write_to_8(buf, table->id);
1033
465
 
1034
466
        dfield_set_data(dfield, buf, 8);
1037
469
        btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
1038
470
                                  BTR_SEARCH_LEAF, &pcur, &mtr);
1039
471
        for (i = 0; i + DATA_N_SYS_COLS < (ulint) table->n_cols; i++) {
1040
 
                const char* err_msg;
1041
472
 
1042
473
                rec = btr_pcur_get_rec(&pcur);
1043
474
 
1044
475
                ut_a(btr_pcur_is_on_user_rec(&pcur));
1045
476
 
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;
 
477
                ut_a(!rec_get_deleted_flag(rec, 0));
 
478
 
 
479
                field = rec_get_nth_field_old(rec, 0, &len);
 
480
                ut_ad(len == 8);
 
481
                ut_a(ut_dulint_cmp(table->id, mach_read_from_8(field)) == 0);
 
482
 
 
483
                field = rec_get_nth_field_old(rec, 1, &len);
 
484
                ut_ad(len == 4);
 
485
                ut_a(i == mach_read_from_4(field));
 
486
 
 
487
                ut_a(name_of_col_is(sys_columns, sys_index, 4, "NAME"));
 
488
 
 
489
                field = rec_get_nth_field_old(rec, 4, &len);
 
490
                name = mem_heap_strdupl(heap, (char*) field, len);
 
491
 
 
492
                field = rec_get_nth_field_old(rec, 5, &len);
 
493
                mtype = mach_read_from_4(field);
 
494
 
 
495
                field = rec_get_nth_field_old(rec, 6, &len);
 
496
                prtype = mach_read_from_4(field);
 
497
 
 
498
                if (dtype_get_charset_coll(prtype) == 0
 
499
                    && dtype_is_string_type(mtype)) {
 
500
                        /* The table was created with < 4.1.2. */
 
501
 
 
502
                        if (dtype_is_binary_string_type(mtype, prtype)) {
 
503
                                /* Use the binary collation for
 
504
                                string columns of binary type. */
 
505
 
 
506
                                prtype = dtype_form_prtype(
 
507
                                        prtype,
 
508
                                        DATA_MYSQL_BINARY_CHARSET_COLL);
 
509
                        } else {
 
510
                                /* Use the default charset for
 
511
                                other than binary columns. */
 
512
 
 
513
                                prtype = dtype_form_prtype(
 
514
                                        prtype,
 
515
                                        data_mysql_default_charset_coll);
 
516
                        }
1052
517
                }
1053
518
 
 
519
                field = rec_get_nth_field_old(rec, 7, &len);
 
520
                col_len = mach_read_from_4(field);
 
521
 
 
522
                ut_a(name_of_col_is(sys_columns, sys_index, 8, "PREC"));
 
523
 
 
524
                dict_mem_table_add_col(table, heap, name,
 
525
                                       mtype, prtype, col_len);
1054
526
                btr_pcur_move_to_next_user_rec(&pcur, &mtr);
1055
527
        }
1056
528
 
1058
530
        mtr_commit(&mtr);
1059
531
}
1060
532
 
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 */
 
533
/********************************************************************//**
 
534
Loads definitions for index fields. */
1185
535
static
1186
 
ulint
 
536
void
1187
537
dict_load_fields(
1188
538
/*=============*/
1189
 
        dict_index_t*   index,  /*!< in/out: index whose fields to load */
 
539
        dict_index_t*   index,  /*!< in: index whose fields to load */
1190
540
        mem_heap_t*     heap)   /*!< in: memory heap for temporary storage */
1191
541
{
1192
542
        dict_table_t*   sys_fields;
1194
544
        btr_pcur_t      pcur;
1195
545
        dtuple_t*       tuple;
1196
546
        dfield_t*       dfield;
 
547
        ulint           pos_and_prefix_len;
 
548
        ulint           prefix_len;
1197
549
        const rec_t*    rec;
 
550
        const byte*     field;
 
551
        ulint           len;
1198
552
        byte*           buf;
1199
553
        ulint           i;
1200
554
        mtr_t           mtr;
1201
 
        ulint           error;
1202
555
 
1203
556
        ut_ad(mutex_own(&(dict_sys->mutex)));
1204
557
 
1207
560
        sys_fields = dict_table_get_low("SYS_FIELDS");
1208
561
        sys_index = UT_LIST_GET_FIRST(sys_fields->indexes);
1209
562
        ut_a(!dict_table_is_comp(sys_fields));
1210
 
        ut_a(name_of_col_is(sys_fields, sys_index, 4, "COL_NAME"));
1211
563
 
1212
564
        tuple = dtuple_create(heap, 1);
1213
565
        dfield = dtuple_get_nth_field(tuple, 0);
1214
566
 
1215
 
        buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
 
567
        buf = mem_heap_alloc(heap, 8);
1216
568
        mach_write_to_8(buf, index->id);
1217
569
 
1218
570
        dfield_set_data(dfield, buf, 8);
1221
573
        btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
1222
574
                                  BTR_SEARCH_LEAF, &pcur, &mtr);
1223
575
        for (i = 0; i < index->n_fields; i++) {
1224
 
                const char* err_msg;
1225
576
 
1226
577
                rec = btr_pcur_get_rec(&pcur);
1227
578
 
1228
579
                ut_a(btr_pcur_is_on_user_rec(&pcur));
1229
580
 
1230
 
                err_msg = dict_load_field_low(buf, index, NULL, NULL, NULL,
1231
 
                                              heap, rec);
 
581
                /* There could be delete marked records in SYS_FIELDS
 
582
                because SYS_FIELDS.INDEX_ID can be updated
 
583
                by ALTER TABLE ADD INDEX. */
1232
584
 
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. */
 
585
                if (rec_get_deleted_flag(rec, 0)) {
1237
586
 
1238
587
                        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
 
                }
 
588
                }
 
589
 
 
590
                field = rec_get_nth_field_old(rec, 0, &len);
 
591
                ut_ad(len == 8);
 
592
 
 
593
                field = rec_get_nth_field_old(rec, 1, &len);
 
594
                ut_a(len == 4);
 
595
 
 
596
                /* The next field stores the field position in the index
 
597
                and a possible column prefix length if the index field
 
598
                does not contain the whole column. The storage format is
 
599
                like this: if there is at least one prefix field in the index,
 
600
                then the HIGH 2 bytes contain the field number (== i) and the
 
601
                low 2 bytes the prefix length for the field. Otherwise the
 
602
                field number (== i) is contained in the 2 LOW bytes. */
 
603
 
 
604
                pos_and_prefix_len = mach_read_from_4(field);
 
605
 
 
606
                ut_a((pos_and_prefix_len & 0xFFFFUL) == i
 
607
                     || (pos_and_prefix_len & 0xFFFF0000UL) == (i << 16));
 
608
 
 
609
                if ((i == 0 && pos_and_prefix_len > 0)
 
610
                    || (pos_and_prefix_len & 0xFFFF0000UL) > 0) {
 
611
 
 
612
                        prefix_len = pos_and_prefix_len & 0xFFFFUL;
 
613
                } else {
 
614
                        prefix_len = 0;
 
615
                }
 
616
 
 
617
                ut_a(name_of_col_is(sys_fields, sys_index, 4, "COL_NAME"));
 
618
 
 
619
                field = rec_get_nth_field_old(rec, 4, &len);
 
620
 
 
621
                dict_mem_index_add_field(index,
 
622
                                         mem_heap_strdupl(heap,
 
623
                                                          (char*) field, len),
 
624
                                         prefix_len);
 
625
 
1244
626
next_rec:
1245
627
                btr_pcur_move_to_next_user_rec(&pcur, &mtr);
1246
628
        }
1247
629
 
1248
 
        error = DB_SUCCESS;
1249
 
func_exit:
1250
630
        btr_pcur_close(&pcur);
1251
631
        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
632
}
1382
633
 
1383
634
/********************************************************************//**
1389
640
ulint
1390
641
dict_load_indexes(
1391
642
/*==============*/
1392
 
        dict_table_t*   table,  /*!< in/out: table */
 
643
        dict_table_t*   table,  /*!< in: table */
1393
644
        mem_heap_t*     heap)   /*!< in: memory heap for temporary storage */
1394
645
{
1395
646
        dict_table_t*   sys_indexes;
1396
647
        dict_index_t*   sys_index;
 
648
        dict_index_t*   index;
1397
649
        btr_pcur_t      pcur;
1398
650
        dtuple_t*       tuple;
1399
651
        dfield_t*       dfield;
1400
652
        const rec_t*    rec;
 
653
        const byte*     field;
 
654
        ulint           len;
 
655
        ulint           name_len;
 
656
        char*           name_buf;
 
657
        ulint           type;
 
658
        ulint           space;
 
659
        ulint           page_no;
 
660
        ulint           n_fields;
1401
661
        byte*           buf;
 
662
        ibool           is_sys_table;
 
663
        dulint          id;
1402
664
        mtr_t           mtr;
1403
665
        ulint           error = DB_SUCCESS;
1404
666
 
1405
667
        ut_ad(mutex_own(&(dict_sys->mutex)));
1406
668
 
 
669
        if ((ut_dulint_get_high(table->id) == 0)
 
670
            && (ut_dulint_get_low(table->id) < DICT_HDR_FIRST_ID)) {
 
671
                is_sys_table = TRUE;
 
672
        } else {
 
673
                is_sys_table = FALSE;
 
674
        }
 
675
 
1407
676
        mtr_start(&mtr);
1408
677
 
1409
678
        sys_indexes = dict_table_get_low("SYS_INDEXES");
1410
679
        sys_index = UT_LIST_GET_FIRST(sys_indexes->indexes);
1411
680
        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
681
 
1415
682
        tuple = dtuple_create(heap, 1);
1416
683
        dfield = dtuple_get_nth_field(tuple, 0);
1417
684
 
1418
 
        buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
 
685
        buf = mem_heap_alloc(heap, 8);
1419
686
        mach_write_to_8(buf, table->id);
1420
687
 
1421
688
        dfield_set_data(dfield, buf, 8);
1424
691
        btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
1425
692
                                  BTR_SEARCH_LEAF, &pcur, &mtr);
1426
693
        for (;;) {
1427
 
                dict_index_t*   index = NULL;
1428
 
                const char*     err_msg;
1429
 
 
1430
694
                if (!btr_pcur_is_on_user_rec(&pcur)) {
1431
695
 
1432
696
                        break;
1434
698
 
1435
699
                rec = btr_pcur_get_rec(&pcur);
1436
700
 
1437
 
                err_msg = dict_load_index_low(buf, table->name, heap, rec,
1438
 
                                              TRUE, &index);
1439
 
                ut_ad((index == NULL) == (err_msg != NULL));
 
701
                field = rec_get_nth_field_old(rec, 0, &len);
 
702
                ut_ad(len == 8);
1440
703
 
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. */
 
704
                if (ut_memcmp(buf, field, len) != 0) {
1444
705
                        break;
1445
 
                } else if (err_msg == dict_load_index_del) {
1446
 
                        /* Skip delete-marked records. */
 
706
                } else if (rec_get_deleted_flag(rec, 0)) {
 
707
                        /* Skip delete marked records */
1447
708
                        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
709
                }
1453
710
 
1454
 
                ut_ad(index);
 
711
                field = rec_get_nth_field_old(rec, 1, &len);
 
712
                ut_ad(len == 8);
 
713
                id = mach_read_from_8(field);
 
714
 
 
715
                ut_a(name_of_col_is(sys_indexes, sys_index, 4, "NAME"));
 
716
 
 
717
                field = rec_get_nth_field_old(rec, 4, &name_len);
 
718
                name_buf = mem_heap_strdupl(heap, (char*) field, name_len);
 
719
 
 
720
                field = rec_get_nth_field_old(rec, 5, &len);
 
721
                n_fields = mach_read_from_4(field);
 
722
 
 
723
                field = rec_get_nth_field_old(rec, 6, &len);
 
724
                type = mach_read_from_4(field);
 
725
 
 
726
                field = rec_get_nth_field_old(rec, 7, &len);
 
727
                space = mach_read_from_4(field);
 
728
 
 
729
                ut_a(name_of_col_is(sys_indexes, sys_index, 8, "PAGE_NO"));
 
730
 
 
731
                field = rec_get_nth_field_old(rec, 8, &len);
 
732
                page_no = mach_read_from_4(field);
1455
733
 
1456
734
                /* We check for unsupported types first, so that the
1457
735
                subsequent checks are relevant for the supported types. */
1458
 
                if (index->type & ~(DICT_CLUSTERED | DICT_UNIQUE)) {
 
736
                if (type & ~(DICT_CLUSTERED | DICT_UNIQUE)) {
1459
737
 
1460
738
                        fprintf(stderr,
1461
739
                                "InnoDB: Error: unknown type %lu"
1462
740
                                " of index %s of table %s\n",
1463
 
                                (ulong) index->type, index->name, table->name);
 
741
                                (ulong) type, name_buf, table->name);
1464
742
 
1465
743
                        error = DB_UNSUPPORTED;
1466
 
                        dict_mem_index_free(index);
1467
744
                        goto func_exit;
1468
 
                } else if (index->page == FIL_NULL) {
 
745
                } else if (page_no == FIL_NULL) {
1469
746
 
1470
747
                        fprintf(stderr,
1471
748
                                "InnoDB: Error: trying to load index %s"
1472
749
                                " for table %s\n"
1473
750
                                "InnoDB: but the index tree has been freed!\n",
1474
 
                                index->name, table->name);
 
751
                                name_buf, table->name);
1475
752
 
1476
 
corrupted:
1477
 
                        dict_mem_index_free(index);
1478
753
                        error = DB_CORRUPTION;
1479
754
                        goto func_exit;
1480
 
                } else if (!dict_index_is_clust(index)
1481
 
                           && NULL == dict_table_get_first_index(table)) {
 
755
                } else if ((type & DICT_CLUSTERED) == 0
 
756
                            && NULL == dict_table_get_first_index(table)) {
1482
757
 
1483
758
                        fputs("InnoDB: Error: trying to load index ",
1484
759
                              stderr);
1485
 
                        ut_print_name(stderr, NULL, FALSE, index->name);
 
760
                        ut_print_name(stderr, NULL, FALSE, name_buf);
1486
761
                        fputs(" for table ", stderr);
1487
762
                        ut_print_name(stderr, NULL, TRUE, table->name);
1488
763
                        fputs("\nInnoDB: but the first index"
1489
764
                              " is not clustered!\n", stderr);
1490
765
 
1491
 
                        goto corrupted;
1492
 
                } else if (table->id < DICT_HDR_FIRST_ID
1493
 
                           && (dict_index_is_clust(index)
 
766
                        error = DB_CORRUPTION;
 
767
                        goto func_exit;
 
768
                } else if (is_sys_table
 
769
                           && ((type & DICT_CLUSTERED)
1494
770
                               || ((table == dict_sys->sys_tables)
1495
 
                                   && !strcmp("ID_IND", index->name)))) {
 
771
                                   && (name_len == (sizeof "ID_IND") - 1)
 
772
                                   && (0 == ut_memcmp(name_buf,
 
773
                                                      "ID_IND", name_len))))) {
1496
774
 
1497
775
                        /* The index was created in memory already at booting
1498
776
                        of the database server */
1499
 
                        dict_mem_index_free(index);
1500
777
                } else {
 
778
                        index = dict_mem_index_create(table->name, name_buf,
 
779
                                                      space, type, n_fields);
 
780
                        index->id = id;
 
781
 
1501
782
                        dict_load_fields(index, heap);
1502
 
                        error = dict_index_add_to_cache(table, index,
1503
 
                                                        index->page, FALSE);
 
783
                        error = dict_index_add_to_cache(table, index, page_no,
 
784
                                                        FALSE);
1504
785
                        /* The data dictionary tables should never contain
1505
786
                        invalid index definitions.  If we ignored this error
1506
787
                        and simply did not load this index definition, the
1524
805
}
1525
806
 
1526
807
/********************************************************************//**
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
808
Loads a table definition and also all its index definitions, and also
1675
809
the cluster definition if the table is a member in a cluster. Also loads
1676
810
all foreign key constraints where the foreign key is in the table or where
1683
817
dict_table_t*
1684
818
dict_load_table(
1685
819
/*============*/
1686
 
        const char*     name,   /*!< in: table name in the
 
820
        const char*     name)   /*!< in: table name in the
1687
821
                                databasename/tablename format */
1688
 
        ibool           cached) /*!< in: TRUE=add to cache, FALSE=do not */
1689
822
{
 
823
        ibool           ibd_file_missing        = FALSE;
1690
824
        dict_table_t*   table;
1691
825
        dict_table_t*   sys_tables;
1692
826
        btr_pcur_t      pcur;
1697
831
        const rec_t*    rec;
1698
832
        const byte*     field;
1699
833
        ulint           len;
 
834
        ulint           space;
 
835
        ulint           n_cols;
 
836
        ulint           flags;
1700
837
        ulint           err;
1701
 
        const char*     err_msg;
1702
838
        mtr_t           mtr;
1703
839
 
1704
840
        ut_ad(mutex_own(&(dict_sys->mutex)));
1710
846
        sys_tables = dict_table_get_low("SYS_TABLES");
1711
847
        sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
1712
848
        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
849
 
1719
850
        tuple = dtuple_create(heap, 1);
1720
851
        dfield = dtuple_get_nth_field(tuple, 0);
1745
876
                goto err_exit;
1746
877
        }
1747
878
 
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;
 
879
        ut_a(name_of_col_is(sys_tables, sys_index, 9, "SPACE"));
 
880
 
 
881
        field = rec_get_nth_field_old(rec, 9, &len);
 
882
        space = mach_read_from_4(field);
 
883
 
 
884
        /* Check if the tablespace exists and has the right name */
 
885
        if (space != 0) {
 
886
                flags = dict_sys_tables_get_flags(rec);
 
887
 
 
888
                if (UNIV_UNLIKELY(flags == ULINT_UNDEFINED)) {
 
889
                        field = rec_get_nth_field_old(rec, 5, &len);
 
890
                        flags = mach_read_from_4(field);
 
891
 
 
892
                        ut_print_timestamp(stderr);
 
893
                        fputs("  InnoDB: Error: table ", stderr);
 
894
                        ut_print_filename(stderr, name);
 
895
                        fprintf(stderr, "\n"
 
896
                                "InnoDB: in InnoDB data dictionary"
 
897
                                " has unknown type %lx.\n",
 
898
                                (ulong) flags);
 
899
                        goto err_exit;
 
900
                }
 
901
 
 
902
                if (fil_space_for_table_exists_in_mem(space, name, FALSE,
 
903
                                                      FALSE, FALSE)) {
 
904
                        /* Ok; (if we did a crash recovery then the tablespace
 
905
                        can already be in the memory cache) */
1768
906
                } else {
 
907
                        /* In >= 4.1.9, InnoDB scans the data dictionary also
 
908
                        at a normal mysqld startup. It is an error if the
 
909
                        space object does not exist in memory. */
 
910
 
1769
911
                        ut_print_timestamp(stderr);
1770
912
                        fprintf(stderr,
1771
 
                                "  InnoDB: error: space object of table ");
1772
 
                        ut_print_filename(stderr, name);
1773
 
                        fprintf(stderr, ",\n"
 
913
                                "  InnoDB: error: space object of table %s,\n"
1774
914
                                "InnoDB: space id %lu did not exist in memory."
1775
915
                                " Retrying an open.\n",
1776
 
                                (ulong) table->space);
 
916
                                name, (ulong)space);
1777
917
                        /* Try to open the tablespace */
1778
918
                        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 */
 
919
                                    TRUE, space, flags, name)) {
 
920
                                /* We failed to find a sensible tablespace
 
921
                                file */
1784
922
 
1785
 
                                table->ibd_file_missing = TRUE;
 
923
                                ibd_file_missing = TRUE;
1786
924
                        }
1787
925
                }
1788
 
        }
 
926
        } else {
 
927
                flags = 0;
 
928
        }
 
929
 
 
930
        ut_a(name_of_col_is(sys_tables, sys_index, 4, "N_COLS"));
 
931
 
 
932
        field = rec_get_nth_field_old(rec, 4, &len);
 
933
        n_cols = mach_read_from_4(field);
 
934
 
 
935
        /* The high-order bit of N_COLS is the "compact format" flag. */
 
936
        if (n_cols & 0x80000000UL) {
 
937
                flags |= DICT_TF_COMPACT;
 
938
        }
 
939
 
 
940
        table = dict_mem_table_create(name, space, n_cols & ~0x80000000UL,
 
941
                                      flags);
 
942
 
 
943
        table->ibd_file_missing = (unsigned int) ibd_file_missing;
 
944
 
 
945
        ut_a(name_of_col_is(sys_tables, sys_index, 3, "ID"));
 
946
 
 
947
        field = rec_get_nth_field_old(rec, 3, &len);
 
948
        table->id = mach_read_from_8(field);
1789
949
 
1790
950
        btr_pcur_close(&pcur);
1791
951
        mtr_commit(&mtr);
1792
952
 
1793
953
        dict_load_columns(table, heap);
1794
954
 
1795
 
        if (cached) {
1796
 
                dict_table_add_to_cache(table, heap);
1797
 
        } else {
1798
 
                dict_table_add_system_columns(table, heap);
1799
 
        }
 
955
        dict_table_add_to_cache(table, heap);
1800
956
 
1801
957
        mem_heap_empty(heap);
1802
958
 
1803
959
        err = dict_load_indexes(table, heap);
1804
960
 
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
961
        /* If the force recovery flag is set, we open the table irrespective
1810
962
        of the error condition, since the user may want to dump data from the
1811
963
        clustered index. However we load the foreign key information only if
1812
964
        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
 
                }
 
965
        if (err == DB_SUCCESS) {
 
966
                err = dict_load_foreigns(table->name, TRUE);
1823
967
        } else if (!srv_force_recovery) {
1824
968
                dict_table_remove_from_cache(table);
1825
969
                table = NULL;
1860
1004
dict_table_t*
1861
1005
dict_load_table_on_id(
1862
1006
/*==================*/
1863
 
        table_id_t      table_id)       /*!< in: table id */
 
1007
        dulint  table_id)       /*!< in: table id */
1864
1008
{
1865
1009
        byte            id_buf[8];
1866
1010
        btr_pcur_t      pcur;
1877
1021
 
1878
1022
        ut_ad(mutex_own(&(dict_sys->mutex)));
1879
1023
 
1880
 
        table = NULL;
1881
 
 
1882
1024
        /* NOTE that the operation of this function is protected by
1883
1025
        the dictionary mutex, and therefore no deadlocks can occur
1884
1026
        with other dictionary operations. */
1905
1047
                                  BTR_SEARCH_LEAF, &pcur, &mtr);
1906
1048
        rec = btr_pcur_get_rec(&pcur);
1907
1049
 
1908
 
        if (!btr_pcur_is_on_user_rec(&pcur)) {
 
1050
        if (!btr_pcur_is_on_user_rec(&pcur)
 
1051
            || rec_get_deleted_flag(rec, 0)) {
1909
1052
                /* 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);
 
1053
 
 
1054
                btr_pcur_close(&pcur);
 
1055
                mtr_commit(&mtr);
 
1056
                mem_heap_free(heap);
 
1057
 
 
1058
                return(NULL);
1919
1059
        }
1920
1060
 
1921
1061
        /*---------------------------------------------------*/
1927
1067
        ut_ad(len == 8);
1928
1068
 
1929
1069
        /* 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;
 
1070
        if (ut_dulint_cmp(table_id, mach_read_from_8(field)) != 0) {
 
1071
 
 
1072
                btr_pcur_close(&pcur);
 
1073
                mtr_commit(&mtr);
 
1074
                mem_heap_free(heap);
 
1075
 
 
1076
                return(NULL);
1932
1077
        }
1933
1078
 
1934
1079
        /* Now we get the table name from the record */
1935
1080
        field = rec_get_nth_field_old(rec, 1, &len);
1936
1081
        /* Load the table definition to memory */
1937
 
        table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len),
1938
 
                                TRUE);
1939
 
func_exit:
 
1082
        table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len));
 
1083
 
1940
1084
        btr_pcur_close(&pcur);
1941
1085
        mtr_commit(&mtr);
1942
1086
        mem_heap_free(heap);
1988
1132
 
1989
1133
        ut_ad(mutex_own(&(dict_sys->mutex)));
1990
1134
 
1991
 
        foreign->foreign_col_names = static_cast<const char **>(mem_heap_alloc(
1992
 
                foreign->heap, foreign->n_fields * sizeof(void*)));
 
1135
        foreign->foreign_col_names = mem_heap_alloc(
 
1136
                foreign->heap, foreign->n_fields * sizeof(void*));
1993
1137
 
1994
 
        foreign->referenced_col_names = static_cast<const char **>(mem_heap_alloc(
1995
 
                foreign->heap, foreign->n_fields * sizeof(void*)));
 
1138
        foreign->referenced_col_names = mem_heap_alloc(
 
1139
                foreign->heap, foreign->n_fields * sizeof(void*));
1996
1140
        mtr_start(&mtr);
1997
1141
 
1998
1142
        sys_foreign_cols = dict_table_get_low("SYS_FOREIGN_COLS");
2046
1190
/*==============*/
2047
1191
        const char*     id,     /*!< in: foreign constraint id as a
2048
1192
                                null-terminated string */
2049
 
        ibool           check_charsets,
 
1193
        ibool           check_charsets)
2050
1194
                                /*!< 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
1195
{
2056
1196
        dict_foreign_t* foreign;
2057
1197
        dict_table_t*   sys_foreign;
2065
1205
        ulint           len;
2066
1206
        ulint           n_fields_and_type;
2067
1207
        mtr_t           mtr;
2068
 
        dict_table_t*   for_table;
2069
 
        dict_table_t*   ref_table;
2070
1208
 
2071
1209
        ut_ad(mutex_own(&(dict_sys->mutex)));
2072
1210
 
2151
1289
 
2152
1290
        dict_load_foreign_cols(id, foreign);
2153
1291
 
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
 
        }
 
1292
        /* If the foreign table is not yet in the dictionary cache, we
 
1293
        have to load it so that we are able to make type comparisons
 
1294
        in the next function call. */
 
1295
 
 
1296
        dict_table_get_low(foreign->foreign_table_name);
2202
1297
 
2203
1298
        /* Note that there may already be a foreign constraint object in
2204
1299
        the dictionary cache for this constraint: then the following
2223
1318
dict_load_foreigns(
2224
1319
/*===============*/
2225
1320
        const char*     table_name,     /*!< in: table name */
2226
 
        ibool           check_recursive,/*!< in: Whether to check recursive
2227
 
                                        load of tables chained by FK */
2228
1321
        ibool           check_charsets) /*!< in: TRUE=check charset
2229
1322
                                        compatibility */
2230
1323
{
2295
1388
 
2296
1389
        if (0 != cmp_data_data(dfield_get_type(dfield)->mtype,
2297
1390
                               dfield_get_type(dfield)->prtype,
2298
 
                               static_cast<const unsigned char *>(dfield_get_data(dfield)),
2299
 
                               dfield_get_len(dfield),
 
1391
                               dfield_get_data(dfield), dfield_get_len(dfield),
2300
1392
                               field, len)) {
2301
1393
 
2302
1394
                goto load_next_index;
2327
1419
 
2328
1420
        /* Load the foreign constraint definition to the dictionary cache */
2329
1421
 
2330
 
        err = dict_load_foreign(id, check_charsets, check_recursive);
 
1422
        err = dict_load_foreign(id, check_charsets);
2331
1423
 
2332
1424
        if (err != DB_SUCCESS) {
2333
1425
                btr_pcur_close(&pcur);
2355
1447
 
2356
1448
                mtr_start(&mtr);
2357
1449
 
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
1450
                goto start_load;
2364
1451
        }
2365
1452