~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2009-01-07 09:27:07 UTC
  • Revision ID: brian@tangent.org-20090107092707-bn67qpdllfcyh3j9
Removing dead field translator code.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*****************************************************************************
2
 
 
3
 
Copyright (C) 1996, 2010, Innobase Oy. All Rights Reserved.
4
 
 
5
 
This program is free software; you can redistribute it and/or modify it under
6
 
the terms of the GNU General Public License as published by the Free Software
7
 
Foundation; version 2 of the License.
8
 
 
9
 
This program is distributed in the hope that it will be useful, but WITHOUT
10
 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
 
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
 
 
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
16
 
 
17
 
*****************************************************************************/
18
 
 
19
 
/**************************************************//**
20
 
@file dict/dict0load.c
 
1
/******************************************************
21
2
Loads to the memory cache database object definitions
22
3
from dictionary tables
23
4
 
 
5
(c) 1996 Innobase Oy
 
6
 
24
7
Created 4/24/1996 Heikki Tuuri
25
8
*******************************************************/
26
9
 
 
10
#include "dict0load.h"
 
11
#ifndef UNIV_HOTBACKUP
27
12
#if defined(BUILD_DRIZZLE)
28
 
# include "config.h"
 
13
# include <drizzled/global.h>
29
14
#else
30
15
# include "mysql_version.h"
31
 
#endif /* BUILD_DRIZZLE */
32
 
#include "dict0load.h"
 
16
#endif /* DRIZZLE */
 
17
#endif /* !UNIV_HOTBACKUP */
33
18
 
34
19
#ifdef UNIV_NONINL
35
20
#include "dict0load.ic"
45
30
#include "srv0start.h"
46
31
#include "srv0srv.h"
47
32
 
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
 
/****************************************************************//**
59
 
Compare the name of an index column.
60
 
@return TRUE if the i'th column of index is 'name'. */
 
33
/********************************************************************
 
34
Returns TRUE if index's i'th column's name is 'name' .*/
61
35
static
62
36
ibool
63
37
name_of_col_is(
64
38
/*===========*/
65
 
        const dict_table_t*     table,  /*!< in: table */
66
 
        const dict_index_t*     index,  /*!< in: index */
67
 
        ulint                   i,      /*!< in: index field offset */
68
 
        const char*             name)   /*!< in: name to compare to */
 
39
                                /* out: */
 
40
        dict_table_t*   table,  /* in: table */
 
41
        dict_index_t*   index,  /* in: index */
 
42
        ulint           i,      /* in:  */
 
43
        const char*     name)   /* in: name to compare to */
69
44
{
70
45
        ulint   tmp = dict_col_get_no(dict_field_get_col(
71
46
                                              dict_index_get_nth_field(
74
49
        return(strcmp(name, dict_table_get_col_name(table, tmp)) == 0);
75
50
}
76
51
 
77
 
/********************************************************************//**
78
 
Finds the first table name in the given database.
79
 
@return own: table name, NULL if does not exist; the caller must free
80
 
the memory in the string! */
 
52
/************************************************************************
 
53
Finds the first table name in the given database. */
81
54
UNIV_INTERN
82
55
char*
83
56
dict_get_first_table_name_in_db(
84
57
/*============================*/
85
 
        const char*     name)   /*!< in: database name which ends in '/' */
 
58
                                /* out, own: table name, NULL if
 
59
                                does not exist; the caller must
 
60
                                free the memory in the string! */
 
61
        const char*     name)   /* in: database name which ends in '/' */
86
62
{
87
63
        dict_table_t*   sys_tables;
88
64
        btr_pcur_t      pcur;
157
133
        goto loop;
158
134
}
159
135
 
160
 
/********************************************************************//**
 
136
/************************************************************************
161
137
Prints to the standard output information on all tables found in the data
162
138
dictionary system table. */
163
139
UNIV_INTERN
165
141
dict_print(void)
166
142
/*============*/
167
143
{
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
144
        dict_table_t*   sys_tables;
583
145
        dict_index_t*   sys_index;
 
146
        dict_table_t*   table;
584
147
        btr_pcur_t      pcur;
585
148
        const rec_t*    rec;
586
149
        const byte*     field;
637
200
 
638
201
                mtr_commit(&mtr);
639
202
 
640
 
                func(func_arg, table_name);
 
203
                table = dict_table_get_low(table_name);
641
204
                mem_free(table_name);
642
205
 
 
206
                if (table == NULL) {
 
207
                        fputs("InnoDB: Failed to load table ", stderr);
 
208
                        ut_print_namel(stderr, NULL, TRUE, (char*) field, len);
 
209
                        putc('\n', stderr);
 
210
                } else {
 
211
                        /* The table definition was corrupt if there
 
212
                        is no index */
 
213
 
 
214
                        if (dict_table_get_first_index(table)) {
 
215
                                dict_update_statistics_low(table, TRUE);
 
216
                        }
 
217
 
 
218
                        dict_table_print_low(table);
 
219
                }
 
220
 
643
221
                mtr_start(&mtr);
644
222
 
645
223
                btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
648
226
        goto loop;
649
227
}
650
228
 
651
 
/********************************************************************//**
652
 
Determine the flags of a table described in SYS_TABLES.
653
 
@return compressed page size in kilobytes; or 0 if the tablespace is
654
 
uncompressed, ULINT_UNDEFINED on error */
 
229
/************************************************************************
 
230
Determine the flags of a table described in SYS_TABLES. */
655
231
static
656
232
ulint
657
233
dict_sys_tables_get_flags(
658
234
/*======================*/
659
 
        const rec_t*    rec)    /*!< in: a record of SYS_TABLES */
 
235
                                /* out: compressed page size in kilobytes;
 
236
                                or 0 if the tablespace is uncompressed,
 
237
                                ULINT_UNDEFINED on error */
 
238
        const rec_t*    rec)    /* in: a record of SYS_TABLES */
660
239
{
661
240
        const byte*     field;
662
241
        ulint           len;
672
251
                return(0);
673
252
        }
674
253
 
675
 
        field = rec_get_nth_field_old(rec, 4/*N_COLS*/, &len);
 
254
        field = rec_get_nth_field_old(rec, 4, &len);
676
255
        n_cols = mach_read_from_4(field);
677
256
 
678
257
        if (UNIV_UNLIKELY(!(n_cols & 0x80000000UL))) {
702
281
                return(ULINT_UNDEFINED);
703
282
        }
704
283
 
705
 
        if (UNIV_UNLIKELY(flags & (SIZE_MAX << DICT_TF_BITS))) {
 
284
        if (UNIV_UNLIKELY(flags & (~0 << DICT_TF_BITS))) {
706
285
                /* Some unused bits are set. */
707
286
                return(ULINT_UNDEFINED);
708
287
        }
710
289
        return(flags);
711
290
}
712
291
 
713
 
/********************************************************************//**
 
292
/************************************************************************
714
293
In a crash recovery we already have all the tablespace objects created.
715
294
This function compares the space id information in the InnoDB data dictionary
716
295
to what we already read with fil_load_single_table_tablespaces().
722
301
void
723
302
dict_check_tablespaces_and_store_max_id(
724
303
/*====================================*/
725
 
        ibool   in_crash_recovery)      /*!< in: are we doing a crash recovery */
 
304
        ibool   in_crash_recovery)      /* in: are we doing a crash recovery */
726
305
{
727
306
        dict_table_t*   sys_tables;
728
307
        dict_index_t*   sys_index;
729
308
        btr_pcur_t      pcur;
730
309
        const rec_t*    rec;
731
 
        ulint           max_space_id;
 
310
        ulint           max_space_id    = 0;
732
311
        mtr_t           mtr;
733
312
 
734
313
        mutex_enter(&(dict_sys->mutex));
739
318
        sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
740
319
        ut_a(!dict_table_is_comp(sys_tables));
741
320
 
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
321
        btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
748
322
                                    TRUE, &mtr);
749
323
loop:
807
381
 
808
382
                mtr_commit(&mtr);
809
383
 
810
 
                if (space_id == 0) {
811
 
                        /* The system tablespace always exists. */
812
 
                } else if (in_crash_recovery) {
 
384
                if (space_id != 0 && in_crash_recovery) {
813
385
                        /* 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 {
 
386
                        exists; print a warning to the .err log if not */
 
387
 
 
388
                        fil_space_for_table_exists_in_mem(space_id, name,
 
389
                                                          FALSE, TRUE, TRUE);
 
390
                }
 
391
 
 
392
                if (space_id != 0 && !in_crash_recovery) {
839
393
                        /* It is a normal database startup: create the space
840
394
                        object and check that the .ibd file exists. */
841
395
 
857
411
        goto loop;
858
412
}
859
413
 
860
 
/********************************************************************//**
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 */
 
414
/************************************************************************
 
415
Loads definitions for table columns. */
 
416
static
 
417
void
 
418
dict_load_columns(
 
419
/*==============*/
 
420
        dict_table_t*   table,  /* in: table */
 
421
        mem_heap_t*     heap)   /* in: memory heap for temporary storage */
879
422
{
 
423
        dict_table_t*   sys_columns;
 
424
        dict_index_t*   sys_index;
 
425
        btr_pcur_t      pcur;
 
426
        dtuple_t*       tuple;
 
427
        dfield_t*       dfield;
 
428
        const rec_t*    rec;
 
429
        const byte*     field;
 
430
        ulint           len;
 
431
        byte*           buf;
880
432
        char*           name;
881
 
        const byte*     field;
882
 
        ulint           len;
883
433
        ulint           mtype;
884
434
        ulint           prtype;
885
435
        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
436
        ulint           i;
1015
437
        mtr_t           mtr;
1016
438
 
1022
444
        sys_index = UT_LIST_GET_FIRST(sys_columns->indexes);
1023
445
        ut_a(!dict_table_is_comp(sys_columns));
1024
446
 
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
447
        tuple = dtuple_create(heap, 1);
1029
448
        dfield = dtuple_get_nth_field(tuple, 0);
1030
449
 
1031
 
        buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
 
450
        buf = mem_heap_alloc(heap, 8);
1032
451
        mach_write_to_8(buf, table->id);
1033
452
 
1034
453
        dfield_set_data(dfield, buf, 8);
1037
456
        btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
1038
457
                                  BTR_SEARCH_LEAF, &pcur, &mtr);
1039
458
        for (i = 0; i + DATA_N_SYS_COLS < (ulint) table->n_cols; i++) {
1040
 
                const char* err_msg;
1041
459
 
1042
460
                rec = btr_pcur_get_rec(&pcur);
1043
461
 
1044
462
                ut_a(btr_pcur_is_on_user_rec(&pcur));
1045
463
 
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;
 
464
                ut_a(!rec_get_deleted_flag(rec, 0));
 
465
 
 
466
                field = rec_get_nth_field_old(rec, 0, &len);
 
467
                ut_ad(len == 8);
 
468
                ut_a(ut_dulint_cmp(table->id, mach_read_from_8(field)) == 0);
 
469
 
 
470
                field = rec_get_nth_field_old(rec, 1, &len);
 
471
                ut_ad(len == 4);
 
472
                ut_a(i == mach_read_from_4(field));
 
473
 
 
474
                ut_a(name_of_col_is(sys_columns, sys_index, 4, "NAME"));
 
475
 
 
476
                field = rec_get_nth_field_old(rec, 4, &len);
 
477
                name = mem_heap_strdupl(heap, (char*) field, len);
 
478
 
 
479
                field = rec_get_nth_field_old(rec, 5, &len);
 
480
                mtype = mach_read_from_4(field);
 
481
 
 
482
                field = rec_get_nth_field_old(rec, 6, &len);
 
483
                prtype = mach_read_from_4(field);
 
484
 
 
485
                if (dtype_get_charset_coll(prtype) == 0
 
486
                    && dtype_is_string_type(mtype)) {
 
487
                        /* The table was created with < 4.1.2. */
 
488
 
 
489
                        if (dtype_is_binary_string_type(mtype, prtype)) {
 
490
                                /* Use the binary collation for
 
491
                                string columns of binary type. */
 
492
 
 
493
                                prtype = dtype_form_prtype(
 
494
                                        prtype,
 
495
                                        DATA_MYSQL_BINARY_CHARSET_COLL);
 
496
                        } else {
 
497
                                /* Use the default charset for
 
498
                                other than binary columns. */
 
499
 
 
500
                                prtype = dtype_form_prtype(
 
501
                                        prtype,
 
502
                                        data_mysql_default_charset_coll);
 
503
                        }
1052
504
                }
1053
505
 
 
506
                field = rec_get_nth_field_old(rec, 7, &len);
 
507
                col_len = mach_read_from_4(field);
 
508
 
 
509
                ut_a(name_of_col_is(sys_columns, sys_index, 8, "PREC"));
 
510
 
 
511
                dict_mem_table_add_col(table, heap, name,
 
512
                                       mtype, prtype, col_len);
1054
513
                btr_pcur_move_to_next_user_rec(&pcur, &mtr);
1055
514
        }
1056
515
 
1058
517
        mtr_commit(&mtr);
1059
518
}
1060
519
 
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 */
 
520
/************************************************************************
 
521
Loads definitions for index fields. */
1185
522
static
1186
 
ulint
 
523
void
1187
524
dict_load_fields(
1188
525
/*=============*/
1189
 
        dict_index_t*   index,  /*!< in/out: index whose fields to load */
1190
 
        mem_heap_t*     heap)   /*!< in: memory heap for temporary storage */
 
526
        dict_index_t*   index,  /* in: index whose fields to load */
 
527
        mem_heap_t*     heap)   /* in: memory heap for temporary storage */
1191
528
{
1192
529
        dict_table_t*   sys_fields;
1193
530
        dict_index_t*   sys_index;
1194
531
        btr_pcur_t      pcur;
1195
532
        dtuple_t*       tuple;
1196
533
        dfield_t*       dfield;
 
534
        ulint           pos_and_prefix_len;
 
535
        ulint           prefix_len;
1197
536
        const rec_t*    rec;
 
537
        const byte*     field;
 
538
        ulint           len;
1198
539
        byte*           buf;
1199
540
        ulint           i;
1200
541
        mtr_t           mtr;
1201
 
        ulint           error;
1202
542
 
1203
543
        ut_ad(mutex_own(&(dict_sys->mutex)));
1204
544
 
1207
547
        sys_fields = dict_table_get_low("SYS_FIELDS");
1208
548
        sys_index = UT_LIST_GET_FIRST(sys_fields->indexes);
1209
549
        ut_a(!dict_table_is_comp(sys_fields));
1210
 
        ut_a(name_of_col_is(sys_fields, sys_index, 4, "COL_NAME"));
1211
550
 
1212
551
        tuple = dtuple_create(heap, 1);
1213
552
        dfield = dtuple_get_nth_field(tuple, 0);
1214
553
 
1215
 
        buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
 
554
        buf = mem_heap_alloc(heap, 8);
1216
555
        mach_write_to_8(buf, index->id);
1217
556
 
1218
557
        dfield_set_data(dfield, buf, 8);
1221
560
        btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
1222
561
                                  BTR_SEARCH_LEAF, &pcur, &mtr);
1223
562
        for (i = 0; i < index->n_fields; i++) {
1224
 
                const char* err_msg;
1225
563
 
1226
564
                rec = btr_pcur_get_rec(&pcur);
1227
565
 
1228
566
                ut_a(btr_pcur_is_on_user_rec(&pcur));
1229
567
 
1230
 
                err_msg = dict_load_field_low(buf, index, NULL, NULL, NULL,
1231
 
                                              heap, rec);
 
568
                /* There could be delete marked records in SYS_FIELDS
 
569
                because SYS_FIELDS.INDEX_ID can be updated
 
570
                by ALTER TABLE ADD INDEX. */
1232
571
 
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. */
 
572
                if (rec_get_deleted_flag(rec, 0)) {
1237
573
 
1238
574
                        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
 
                }
 
575
                }
 
576
 
 
577
                field = rec_get_nth_field_old(rec, 0, &len);
 
578
                ut_ad(len == 8);
 
579
 
 
580
                field = rec_get_nth_field_old(rec, 1, &len);
 
581
                ut_a(len == 4);
 
582
 
 
583
                /* The next field stores the field position in the index
 
584
                and a possible column prefix length if the index field
 
585
                does not contain the whole column. The storage format is
 
586
                like this: if there is at least one prefix field in the index,
 
587
                then the HIGH 2 bytes contain the field number (== i) and the
 
588
                low 2 bytes the prefix length for the field. Otherwise the
 
589
                field number (== i) is contained in the 2 LOW bytes. */
 
590
 
 
591
                pos_and_prefix_len = mach_read_from_4(field);
 
592
 
 
593
                ut_a((pos_and_prefix_len & 0xFFFFUL) == i
 
594
                     || (pos_and_prefix_len & 0xFFFF0000UL) == (i << 16));
 
595
 
 
596
                if ((i == 0 && pos_and_prefix_len > 0)
 
597
                    || (pos_and_prefix_len & 0xFFFF0000UL) > 0) {
 
598
 
 
599
                        prefix_len = pos_and_prefix_len & 0xFFFFUL;
 
600
                } else {
 
601
                        prefix_len = 0;
 
602
                }
 
603
 
 
604
                ut_a(name_of_col_is(sys_fields, sys_index, 4, "COL_NAME"));
 
605
 
 
606
                field = rec_get_nth_field_old(rec, 4, &len);
 
607
 
 
608
                dict_mem_index_add_field(index,
 
609
                                         mem_heap_strdupl(heap,
 
610
                                                          (char*) field, len),
 
611
                                         prefix_len);
 
612
 
1244
613
next_rec:
1245
614
                btr_pcur_move_to_next_user_rec(&pcur, &mtr);
1246
615
        }
1247
616
 
1248
 
        error = DB_SUCCESS;
1249
 
func_exit:
1250
617
        btr_pcur_close(&pcur);
1251
618
        mtr_commit(&mtr);
1252
 
        return(error);
1253
619
}
1254
620
 
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 */
 
621
/************************************************************************
 
622
Loads definitions for table indexes. Adds them to the data dictionary
 
623
cache. */
 
624
static
 
625
ulint
 
626
dict_load_indexes(
 
627
/*==============*/
 
628
                                /* out: DB_SUCCESS if ok, DB_CORRUPTION
 
629
                                if corruption of dictionary table or
 
630
                                DB_UNSUPPORTED if table has unknown index
 
631
                                type */
 
632
        dict_table_t*   table,  /* in: table */
 
633
        mem_heap_t*     heap)   /* in: memory heap for temporary storage */
1280
634
{
 
635
        dict_table_t*   sys_indexes;
 
636
        dict_index_t*   sys_index;
 
637
        dict_index_t*   index;
 
638
        btr_pcur_t      pcur;
 
639
        dtuple_t*       tuple;
 
640
        dfield_t*       dfield;
 
641
        const rec_t*    rec;
1281
642
        const byte*     field;
1282
643
        ulint           len;
1283
644
        ulint           name_len;
1284
645
        char*           name_buf;
1285
 
        index_id_t      id;
 
646
        ulint           type;
 
647
        ulint           space;
 
648
        ulint           page_no;
1286
649
        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
 
}
1382
 
 
1383
 
/********************************************************************//**
1384
 
Loads definitions for table indexes. Adds them to the data dictionary
1385
 
cache.
1386
 
@return DB_SUCCESS if ok, DB_CORRUPTION if corruption of dictionary
1387
 
table or DB_UNSUPPORTED if table has unknown index type */
1388
 
static
1389
 
ulint
1390
 
dict_load_indexes(
1391
 
/*==============*/
1392
 
        dict_table_t*   table,  /*!< in/out: table */
1393
 
        mem_heap_t*     heap)   /*!< in: memory heap for temporary storage */
1394
 
{
1395
 
        dict_table_t*   sys_indexes;
1396
 
        dict_index_t*   sys_index;
1397
 
        btr_pcur_t      pcur;
1398
 
        dtuple_t*       tuple;
1399
 
        dfield_t*       dfield;
1400
 
        const rec_t*    rec;
1401
650
        byte*           buf;
 
651
        ibool           is_sys_table;
 
652
        dulint          id;
1402
653
        mtr_t           mtr;
1403
654
        ulint           error = DB_SUCCESS;
1404
655
 
1405
656
        ut_ad(mutex_own(&(dict_sys->mutex)));
1406
657
 
 
658
        if ((ut_dulint_get_high(table->id) == 0)
 
659
            && (ut_dulint_get_low(table->id) < DICT_HDR_FIRST_ID)) {
 
660
                is_sys_table = TRUE;
 
661
        } else {
 
662
                is_sys_table = FALSE;
 
663
        }
 
664
 
1407
665
        mtr_start(&mtr);
1408
666
 
1409
667
        sys_indexes = dict_table_get_low("SYS_INDEXES");
1410
668
        sys_index = UT_LIST_GET_FIRST(sys_indexes->indexes);
1411
669
        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
670
 
1415
671
        tuple = dtuple_create(heap, 1);
1416
672
        dfield = dtuple_get_nth_field(tuple, 0);
1417
673
 
1418
 
        buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
 
674
        buf = mem_heap_alloc(heap, 8);
1419
675
        mach_write_to_8(buf, table->id);
1420
676
 
1421
677
        dfield_set_data(dfield, buf, 8);
1424
680
        btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
1425
681
                                  BTR_SEARCH_LEAF, &pcur, &mtr);
1426
682
        for (;;) {
1427
 
                dict_index_t*   index = NULL;
1428
 
                const char*     err_msg;
1429
 
 
1430
683
                if (!btr_pcur_is_on_user_rec(&pcur)) {
1431
684
 
1432
685
                        break;
1434
687
 
1435
688
                rec = btr_pcur_get_rec(&pcur);
1436
689
 
1437
 
                err_msg = dict_load_index_low(buf, table->name, heap, rec,
1438
 
                                              TRUE, &index);
1439
 
                ut_ad((index == NULL) == (err_msg != NULL));
 
690
                field = rec_get_nth_field_old(rec, 0, &len);
 
691
                ut_ad(len == 8);
1440
692
 
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. */
 
693
                if (ut_memcmp(buf, field, len) != 0) {
1444
694
                        break;
1445
 
                } else if (err_msg == dict_load_index_del) {
1446
 
                        /* Skip delete-marked records. */
 
695
                } else if (rec_get_deleted_flag(rec, 0)) {
 
696
                        /* Skip delete marked records */
1447
697
                        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
698
                }
1453
699
 
1454
 
                ut_ad(index);
 
700
                field = rec_get_nth_field_old(rec, 1, &len);
 
701
                ut_ad(len == 8);
 
702
                id = mach_read_from_8(field);
 
703
 
 
704
                ut_a(name_of_col_is(sys_indexes, sys_index, 4, "NAME"));
 
705
 
 
706
                field = rec_get_nth_field_old(rec, 4, &name_len);
 
707
                name_buf = mem_heap_strdupl(heap, (char*) field, name_len);
 
708
 
 
709
                field = rec_get_nth_field_old(rec, 5, &len);
 
710
                n_fields = mach_read_from_4(field);
 
711
 
 
712
                field = rec_get_nth_field_old(rec, 6, &len);
 
713
                type = mach_read_from_4(field);
 
714
 
 
715
                field = rec_get_nth_field_old(rec, 7, &len);
 
716
                space = mach_read_from_4(field);
 
717
 
 
718
                ut_a(name_of_col_is(sys_indexes, sys_index, 8, "PAGE_NO"));
 
719
 
 
720
                field = rec_get_nth_field_old(rec, 8, &len);
 
721
                page_no = mach_read_from_4(field);
1455
722
 
1456
723
                /* We check for unsupported types first, so that the
1457
724
                subsequent checks are relevant for the supported types. */
1458
 
                if (index->type & ~(DICT_CLUSTERED | DICT_UNIQUE)) {
 
725
                if (type & ~(DICT_CLUSTERED | DICT_UNIQUE)) {
1459
726
 
1460
727
                        fprintf(stderr,
1461
728
                                "InnoDB: Error: unknown type %lu"
1462
729
                                " of index %s of table %s\n",
1463
 
                                (ulong) index->type, index->name, table->name);
 
730
                                (ulong) type, name_buf, table->name);
1464
731
 
1465
732
                        error = DB_UNSUPPORTED;
1466
 
                        dict_mem_index_free(index);
1467
733
                        goto func_exit;
1468
 
                } else if (index->page == FIL_NULL) {
 
734
                } else if (page_no == FIL_NULL) {
1469
735
 
1470
736
                        fprintf(stderr,
1471
737
                                "InnoDB: Error: trying to load index %s"
1472
738
                                " for table %s\n"
1473
739
                                "InnoDB: but the index tree has been freed!\n",
1474
 
                                index->name, table->name);
 
740
                                name_buf, table->name);
1475
741
 
1476
 
corrupted:
1477
 
                        dict_mem_index_free(index);
1478
742
                        error = DB_CORRUPTION;
1479
743
                        goto func_exit;
1480
 
                } else if (!dict_index_is_clust(index)
1481
 
                           && NULL == dict_table_get_first_index(table)) {
 
744
                } else if ((type & DICT_CLUSTERED) == 0
 
745
                            && NULL == dict_table_get_first_index(table)) {
1482
746
 
1483
747
                        fputs("InnoDB: Error: trying to load index ",
1484
748
                              stderr);
1485
 
                        ut_print_name(stderr, NULL, FALSE, index->name);
 
749
                        ut_print_name(stderr, NULL, FALSE, name_buf);
1486
750
                        fputs(" for table ", stderr);
1487
751
                        ut_print_name(stderr, NULL, TRUE, table->name);
1488
752
                        fputs("\nInnoDB: but the first index"
1489
753
                              " is not clustered!\n", stderr);
1490
754
 
1491
 
                        goto corrupted;
1492
 
                } else if (table->id < DICT_HDR_FIRST_ID
1493
 
                           && (dict_index_is_clust(index)
 
755
                        error = DB_CORRUPTION;
 
756
                        goto func_exit;
 
757
                } else if (is_sys_table
 
758
                           && ((type & DICT_CLUSTERED)
1494
759
                               || ((table == dict_sys->sys_tables)
1495
 
                                   && !strcmp("ID_IND", index->name)))) {
 
760
                                   && (name_len == (sizeof "ID_IND") - 1)
 
761
                                   && (0 == ut_memcmp(name_buf,
 
762
                                                      "ID_IND", name_len))))) {
1496
763
 
1497
764
                        /* The index was created in memory already at booting
1498
765
                        of the database server */
1499
 
                        dict_mem_index_free(index);
1500
766
                } else {
 
767
                        index = dict_mem_index_create(table->name, name_buf,
 
768
                                                      space, type, n_fields);
 
769
                        index->id = id;
 
770
 
1501
771
                        dict_load_fields(index, heap);
1502
 
                        error = dict_index_add_to_cache(table, index,
1503
 
                                                        index->page, FALSE);
 
772
                        error = dict_index_add_to_cache(table, index, page_no,
 
773
                                                        FALSE);
1504
774
                        /* The data dictionary tables should never contain
1505
775
                        invalid index definitions.  If we ignored this error
1506
776
                        and simply did not load this index definition, the
1523
793
        return(error);
1524
794
}
1525
795
 
1526
 
/********************************************************************//**
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
 
/********************************************************************//**
 
796
/************************************************************************
1674
797
Loads a table definition and also all its index definitions, and also
1675
798
the cluster definition if the table is a member in a cluster. Also loads
1676
799
all foreign key constraints where the foreign key is in the table or where
1677
800
a foreign key references columns in this table. Adds all these to the data
1678
 
dictionary cache.
1679
 
@return table, NULL if does not exist; if the table is stored in an
1680
 
.ibd file, but the file does not exist, then we set the
1681
 
ibd_file_missing flag TRUE in the table object we return */
 
801
dictionary cache. */
1682
802
UNIV_INTERN
1683
803
dict_table_t*
1684
804
dict_load_table(
1685
805
/*============*/
1686
 
        const char*     name,   /*!< in: table name in the
 
806
                                /* out: table, NULL if does not exist;
 
807
                                if the table is stored in an .ibd file,
 
808
                                but the file does not exist,
 
809
                                then we set the ibd_file_missing flag TRUE
 
810
                                in the table object we return */
 
811
        const char*     name)   /* in: table name in the
1687
812
                                databasename/tablename format */
1688
 
        ibool           cached) /*!< in: TRUE=add to cache, FALSE=do not */
1689
813
{
 
814
        ibool           ibd_file_missing        = FALSE;
1690
815
        dict_table_t*   table;
1691
816
        dict_table_t*   sys_tables;
1692
817
        btr_pcur_t      pcur;
1697
822
        const rec_t*    rec;
1698
823
        const byte*     field;
1699
824
        ulint           len;
 
825
        ulint           space;
 
826
        ulint           n_cols;
 
827
        ulint           flags;
1700
828
        ulint           err;
1701
 
        const char*     err_msg;
1702
829
        mtr_t           mtr;
1703
830
 
1704
831
        ut_ad(mutex_own(&(dict_sys->mutex)));
1710
837
        sys_tables = dict_table_get_low("SYS_TABLES");
1711
838
        sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
1712
839
        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
840
 
1719
841
        tuple = dtuple_create(heap, 1);
1720
842
        dfield = dtuple_get_nth_field(tuple, 0);
1745
867
                goto err_exit;
1746
868
        }
1747
869
 
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;
 
870
        ut_a(name_of_col_is(sys_tables, sys_index, 9, "SPACE"));
 
871
 
 
872
        field = rec_get_nth_field_old(rec, 9, &len);
 
873
        space = mach_read_from_4(field);
 
874
 
 
875
        /* Check if the tablespace exists and has the right name */
 
876
        if (space != 0) {
 
877
                flags = dict_sys_tables_get_flags(rec);
 
878
 
 
879
                if (UNIV_UNLIKELY(flags == ULINT_UNDEFINED)) {
 
880
                        field = rec_get_nth_field_old(rec, 5, &len);
 
881
                        flags = mach_read_from_4(field);
 
882
 
 
883
                        ut_print_timestamp(stderr);
 
884
                        fputs("  InnoDB: Error: table ", stderr);
 
885
                        ut_print_filename(stderr, name);
 
886
                        fprintf(stderr, "\n"
 
887
                                "InnoDB: in InnoDB data dictionary"
 
888
                                " has unknown type %lx.\n",
 
889
                                (ulong) flags);
 
890
                        goto err_exit;
 
891
                }
 
892
 
 
893
                if (fil_space_for_table_exists_in_mem(space, name, FALSE,
 
894
                                                      FALSE, FALSE)) {
 
895
                        /* Ok; (if we did a crash recovery then the tablespace
 
896
                        can already be in the memory cache) */
1768
897
                } else {
 
898
                        /* In >= 4.1.9, InnoDB scans the data dictionary also
 
899
                        at a normal mysqld startup. It is an error if the
 
900
                        space object does not exist in memory. */
 
901
 
1769
902
                        ut_print_timestamp(stderr);
1770
903
                        fprintf(stderr,
1771
 
                                "  InnoDB: error: space object of table ");
1772
 
                        ut_print_filename(stderr, name);
1773
 
                        fprintf(stderr, ",\n"
 
904
                                "  InnoDB: error: space object of table %s,\n"
1774
905
                                "InnoDB: space id %lu did not exist in memory."
1775
906
                                " Retrying an open.\n",
1776
 
                                (ulong) table->space);
 
907
                                name, (ulong)space);
1777
908
                        /* Try to open the tablespace */
1778
909
                        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 */
 
910
                                    TRUE, space, flags, name)) {
 
911
                                /* We failed to find a sensible tablespace
 
912
                                file */
1784
913
 
1785
 
                                table->ibd_file_missing = TRUE;
 
914
                                ibd_file_missing = TRUE;
1786
915
                        }
1787
916
                }
1788
 
        }
 
917
        } else {
 
918
                flags = 0;
 
919
        }
 
920
 
 
921
        ut_a(name_of_col_is(sys_tables, sys_index, 4, "N_COLS"));
 
922
 
 
923
        field = rec_get_nth_field_old(rec, 4, &len);
 
924
        n_cols = mach_read_from_4(field);
 
925
 
 
926
        /* The high-order bit of N_COLS is the "compact format" flag. */
 
927
        if (n_cols & 0x80000000UL) {
 
928
                flags |= DICT_TF_COMPACT;
 
929
        }
 
930
 
 
931
        table = dict_mem_table_create(name, space, n_cols & ~0x80000000UL,
 
932
                                      flags);
 
933
 
 
934
        table->ibd_file_missing = (unsigned int) ibd_file_missing;
 
935
 
 
936
        ut_a(name_of_col_is(sys_tables, sys_index, 3, "ID"));
 
937
 
 
938
        field = rec_get_nth_field_old(rec, 3, &len);
 
939
        table->id = mach_read_from_8(field);
1789
940
 
1790
941
        btr_pcur_close(&pcur);
1791
942
        mtr_commit(&mtr);
1792
943
 
1793
944
        dict_load_columns(table, heap);
1794
945
 
1795
 
        if (cached) {
1796
 
                dict_table_add_to_cache(table, heap);
1797
 
        } else {
1798
 
                dict_table_add_system_columns(table, heap);
1799
 
        }
 
946
        dict_table_add_to_cache(table, heap);
1800
947
 
1801
948
        mem_heap_empty(heap);
1802
949
 
1803
950
        err = dict_load_indexes(table, heap);
1804
 
 
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
 
 
 
951
#ifndef UNIV_HOTBACKUP
1809
952
        /* If the force recovery flag is set, we open the table irrespective
1810
953
        of the error condition, since the user may want to dump data from the
1811
954
        clustered index. However we load the foreign key information only if
1812
955
        all indexes were loaded. */
1813
 
        if (!cached) {
 
956
        if (err != DB_SUCCESS && !srv_force_recovery) {
 
957
                dict_mem_table_free(table);
 
958
                table = NULL;
1814
959
        } 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
 
                }
1823
 
        } else if (!srv_force_recovery) {
1824
 
                dict_table_remove_from_cache(table);
1825
 
                table = NULL;
 
960
                err = dict_load_foreigns(table->name, TRUE);
1826
961
        }
1827
 
#if 0
 
962
# if 0
1828
963
        if (err != DB_SUCCESS && table != NULL) {
1829
964
 
1830
965
                mutex_enter(&dict_foreign_err_mutex);
1847
982
 
1848
983
                mutex_exit(&dict_foreign_err_mutex);
1849
984
        }
1850
 
#endif /* 0 */
 
985
# endif /* 0 */
 
986
#endif /* !UNIV_HOTBACKUP */
1851
987
        mem_heap_free(heap);
1852
988
 
1853
989
        return(table);
1854
990
}
1855
991
 
1856
 
/***********************************************************************//**
1857
 
Loads a table object based on the table id.
1858
 
@return table; NULL if table does not exist */
 
992
/***************************************************************************
 
993
Loads a table object based on the table id. */
1859
994
UNIV_INTERN
1860
995
dict_table_t*
1861
996
dict_load_table_on_id(
1862
997
/*==================*/
1863
 
        table_id_t      table_id)       /*!< in: table id */
 
998
                                /* out: table; NULL if table does not exist */
 
999
        dulint  table_id)       /* in: table id */
1864
1000
{
1865
1001
        byte            id_buf[8];
1866
1002
        btr_pcur_t      pcur;
1877
1013
 
1878
1014
        ut_ad(mutex_own(&(dict_sys->mutex)));
1879
1015
 
1880
 
        table = NULL;
1881
 
 
1882
1016
        /* NOTE that the operation of this function is protected by
1883
1017
        the dictionary mutex, and therefore no deadlocks can occur
1884
1018
        with other dictionary operations. */
1905
1039
                                  BTR_SEARCH_LEAF, &pcur, &mtr);
1906
1040
        rec = btr_pcur_get_rec(&pcur);
1907
1041
 
1908
 
        if (!btr_pcur_is_on_user_rec(&pcur)) {
 
1042
        if (!btr_pcur_is_on_user_rec(&pcur)
 
1043
            || rec_get_deleted_flag(rec, 0)) {
1909
1044
                /* 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);
 
1045
 
 
1046
                btr_pcur_close(&pcur);
 
1047
                mtr_commit(&mtr);
 
1048
                mem_heap_free(heap);
 
1049
 
 
1050
                return(NULL);
1919
1051
        }
1920
1052
 
1921
1053
        /*---------------------------------------------------*/
1927
1059
        ut_ad(len == 8);
1928
1060
 
1929
1061
        /* 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;
 
1062
        if (ut_dulint_cmp(table_id, mach_read_from_8(field)) != 0) {
 
1063
 
 
1064
                btr_pcur_close(&pcur);
 
1065
                mtr_commit(&mtr);
 
1066
                mem_heap_free(heap);
 
1067
 
 
1068
                return(NULL);
1932
1069
        }
1933
1070
 
1934
1071
        /* Now we get the table name from the record */
1935
1072
        field = rec_get_nth_field_old(rec, 1, &len);
1936
1073
        /* Load the table definition to memory */
1937
 
        table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len),
1938
 
                                TRUE);
1939
 
func_exit:
 
1074
        table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len));
 
1075
 
1940
1076
        btr_pcur_close(&pcur);
1941
1077
        mtr_commit(&mtr);
1942
1078
        mem_heap_free(heap);
1944
1080
        return(table);
1945
1081
}
1946
1082
 
1947
 
/********************************************************************//**
 
1083
/************************************************************************
1948
1084
This function is called when the database is booted. Loads system table
1949
1085
index definitions except for the clustered index which is added to the
1950
1086
dictionary cache at booting before calling this function. */
1952
1088
void
1953
1089
dict_load_sys_table(
1954
1090
/*================*/
1955
 
        dict_table_t*   table)  /*!< in: system table */
 
1091
        dict_table_t*   table)  /* in: system table */
1956
1092
{
1957
1093
        mem_heap_t*     heap;
1958
1094
 
1965
1101
        mem_heap_free(heap);
1966
1102
}
1967
1103
 
1968
 
/********************************************************************//**
 
1104
#ifndef UNIV_HOTBACKUP
 
1105
/************************************************************************
1969
1106
Loads foreign key constraint col names (also for the referenced table). */
1970
1107
static
1971
1108
void
1972
1109
dict_load_foreign_cols(
1973
1110
/*===================*/
1974
 
        const char*     id,     /*!< in: foreign constraint id as a
 
1111
        const char*     id,     /* in: foreign constraint id as a
1975
1112
                                null-terminated string */
1976
 
        dict_foreign_t* foreign)/*!< in: foreign constraint object */
 
1113
        dict_foreign_t* foreign)/* in: foreign constraint object */
1977
1114
{
1978
1115
        dict_table_t*   sys_foreign_cols;
1979
1116
        dict_index_t*   sys_index;
1988
1125
 
1989
1126
        ut_ad(mutex_own(&(dict_sys->mutex)));
1990
1127
 
1991
 
        foreign->foreign_col_names = static_cast<const char **>(mem_heap_alloc(
1992
 
                foreign->heap, foreign->n_fields * sizeof(void*)));
 
1128
        foreign->foreign_col_names = mem_heap_alloc(
 
1129
                foreign->heap, foreign->n_fields * sizeof(void*));
1993
1130
 
1994
 
        foreign->referenced_col_names = static_cast<const char **>(mem_heap_alloc(
1995
 
                foreign->heap, foreign->n_fields * sizeof(void*)));
 
1131
        foreign->referenced_col_names = mem_heap_alloc(
 
1132
                foreign->heap, foreign->n_fields * sizeof(void*));
1996
1133
        mtr_start(&mtr);
1997
1134
 
1998
1135
        sys_foreign_cols = dict_table_get_low("SYS_FOREIGN_COLS");
2037
1174
        mtr_commit(&mtr);
2038
1175
}
2039
1176
 
2040
 
/***********************************************************************//**
2041
 
Loads a foreign key constraint to the dictionary cache.
2042
 
@return DB_SUCCESS or error code */
 
1177
/***************************************************************************
 
1178
Loads a foreign key constraint to the dictionary cache. */
2043
1179
static
2044
1180
ulint
2045
1181
dict_load_foreign(
2046
1182
/*==============*/
2047
 
        const char*     id,     /*!< in: foreign constraint id as a
 
1183
                                /* out: DB_SUCCESS or error code */
 
1184
        const char*     id,     /* in: foreign constraint id as a
2048
1185
                                null-terminated string */
2049
 
        ibool           check_charsets,
2050
 
                                /*!< 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 */
 
1186
        ibool           check_charsets)
 
1187
                                /* in: TRUE=check charset compatibility */
2055
1188
{
2056
1189
        dict_foreign_t* foreign;
2057
1190
        dict_table_t*   sys_foreign;
2065
1198
        ulint           len;
2066
1199
        ulint           n_fields_and_type;
2067
1200
        mtr_t           mtr;
2068
 
        dict_table_t*   for_table;
2069
 
        dict_table_t*   ref_table;
2070
1201
 
2071
1202
        ut_ad(mutex_own(&(dict_sys->mutex)));
2072
1203
 
2151
1282
 
2152
1283
        dict_load_foreign_cols(id, foreign);
2153
1284
 
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
 
        }
 
1285
        /* If the foreign table is not yet in the dictionary cache, we
 
1286
        have to load it so that we are able to make type comparisons
 
1287
        in the next function call. */
 
1288
 
 
1289
        dict_table_get_low(foreign->foreign_table_name);
2202
1290
 
2203
1291
        /* Note that there may already be a foreign constraint object in
2204
1292
        the dictionary cache for this constraint: then the following
2211
1299
        return(dict_foreign_add_to_cache(foreign, check_charsets));
2212
1300
}
2213
1301
 
2214
 
/***********************************************************************//**
 
1302
/***************************************************************************
2215
1303
Loads foreign key constraints where the table is either the foreign key
2216
1304
holder or where the table is referenced by a foreign key. Adds these
2217
1305
constraints to the data dictionary. Note that we know that the dictionary
2218
1306
cache already contains all constraints where the other relevant table is
2219
 
already in the dictionary cache.
2220
 
@return DB_SUCCESS or error code */
 
1307
already in the dictionary cache. */
2221
1308
UNIV_INTERN
2222
1309
ulint
2223
1310
dict_load_foreigns(
2224
1311
/*===============*/
2225
 
        const char*     table_name,     /*!< in: table name */
2226
 
        ibool           check_recursive,/*!< in: Whether to check recursive
2227
 
                                        load of tables chained by FK */
2228
 
        ibool           check_charsets) /*!< in: TRUE=check charset
 
1312
                                        /* out: DB_SUCCESS or error code */
 
1313
        const char*     table_name,     /* in: table name */
 
1314
        ibool           check_charsets) /* in: TRUE=check charset
2229
1315
                                        compatibility */
2230
1316
{
2231
1317
        btr_pcur_t      pcur;
2295
1381
 
2296
1382
        if (0 != cmp_data_data(dfield_get_type(dfield)->mtype,
2297
1383
                               dfield_get_type(dfield)->prtype,
2298
 
                               static_cast<const unsigned char *>(dfield_get_data(dfield)),
2299
 
                               dfield_get_len(dfield),
 
1384
                               dfield_get_data(dfield), dfield_get_len(dfield),
2300
1385
                               field, len)) {
2301
1386
 
2302
1387
                goto load_next_index;
2327
1412
 
2328
1413
        /* Load the foreign constraint definition to the dictionary cache */
2329
1414
 
2330
 
        err = dict_load_foreign(id, check_charsets, check_recursive);
 
1415
        err = dict_load_foreign(id, check_charsets);
2331
1416
 
2332
1417
        if (err != DB_SUCCESS) {
2333
1418
                btr_pcur_close(&pcur);
2355
1440
 
2356
1441
                mtr_start(&mtr);
2357
1442
 
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
1443
                goto start_load;
2364
1444
        }
2365
1445
 
2366
1446
        return(DB_SUCCESS);
2367
1447
}
 
1448
#endif /* !UNIV_HOTBACKUP */