~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2010-06-02 22:35:45 UTC
  • mto: This revision was merged to the branch mainline in revision 1586.
  • Revision ID: mordred@inaugust.com-20100602223545-q8ekf9b40a85nwuf
Rearragned unittests into a single exe because of how we need to link it
(thanks lifeless)
Link with server symbols without needing to build a library.
Added an additional atomics test which tests whatever version of the atomics
lib the running platform would actually use.

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