~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Lee Bieber
  • Date: 2010-12-02 18:56:33 UTC
  • mfrom: (1966.3.1 bug683842)
  • mto: This revision was merged to the branch mainline in revision 1969.
  • Revision ID: kalebral@gmail.com-20101202185633-e27o1zhpev18dlsn
Merge Monty - fix bug 683842: remove generic catch blocks       

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (C) 1996, 2010, Innobase Oy. All Rights Reserved.
 
3
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
4
4
 
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
189
189
                const char* err_msg;
190
190
 
191
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));
 
192
                        heap, rec, &table, DICT_TABLE_LOAD_FROM_CACHE
 
193
                        | DICT_TABLE_UPDATE_STATS);
195
194
 
196
195
                mtr_commit(&mtr);
197
196
 
352
351
 
353
352
                /* Update statistics if DICT_TABLE_UPDATE_STATS
354
353
                is set */
355
 
                dict_update_statistics(*table,
356
 
                                       FALSE /* update even if
357
 
                                                initialized */);
 
354
                dict_update_statistics_low(*table, TRUE);
358
355
        }
359
356
 
360
357
        return(NULL);
372
369
        mem_heap_t*     heap,           /*!< in/out: heap memory */
373
370
        const rec_t*    rec,            /*!< in: current SYS_INDEXES rec */
374
371
        dict_index_t*   index,          /*!< out: index to be filled */
375
 
        table_id_t*     table_id)       /*!< out: index table id */
 
372
        dulint*         table_id)       /*!< out: index table id */
376
373
{
377
374
        const char*     err_msg;
378
375
        byte*           buf;
379
376
 
380
 
        buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
 
377
        buf = mem_heap_alloc(heap, 8);
381
378
 
382
379
        /* Parse the record, and get "dict_index_t" struct filled */
383
380
        err_msg = dict_load_index_low(buf, NULL,
398
395
        mem_heap_t*     heap,           /*!< in/out: heap memory */
399
396
        const rec_t*    rec,            /*!< in: current SYS_COLUMNS rec */
400
397
        dict_col_t*     column,         /*!< out: dict_col_t to be filled */
401
 
        table_id_t*     table_id,       /*!< out: table id */
 
398
        dulint*         table_id,       /*!< out: table id */
402
399
        const char**    col_name)       /*!< out: column name */
403
400
{
404
401
        const char*     err_msg;
422
419
        dict_field_t*   sys_field,      /*!< out: dict_field_t to be
423
420
                                        filled */
424
421
        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 */
 
422
        dulint*         index_id,       /*!< out: current index id */
 
423
        dulint          last_id)        /*!< in: previous index id */
427
424
{
428
425
        byte*           buf;
429
426
        byte*           last_index_id;
430
427
        const char*     err_msg;
431
428
 
432
 
        buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
 
429
        buf = mem_heap_alloc(heap, 8);
433
430
 
434
 
        last_index_id = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
 
431
        last_index_id = mem_heap_alloc(heap, 8);
435
432
        mach_write_to_8(last_index_id, last_id);
436
433
 
437
434
        err_msg = dict_load_field_low(buf, NULL, sys_field,
702
699
                return(ULINT_UNDEFINED);
703
700
        }
704
701
 
705
 
        if (UNIV_UNLIKELY(flags & (SIZE_MAX << DICT_TF_BITS))) {
 
702
        if (UNIV_UNLIKELY(flags & (~0 << DICT_TF_BITS))) {
706
703
                /* Some unused bits are set. */
707
704
                return(ULINT_UNDEFINED);
708
705
        }
728
725
        dict_index_t*   sys_index;
729
726
        btr_pcur_t      pcur;
730
727
        const rec_t*    rec;
731
 
        ulint           max_space_id;
 
728
        ulint           max_space_id    = 0;
732
729
        mtr_t           mtr;
733
730
 
734
731
        mutex_enter(&(dict_sys->mutex));
739
736
        sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
740
737
        ut_a(!dict_table_is_comp(sys_tables));
741
738
 
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
739
        btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
748
740
                                    TRUE, &mtr);
749
741
loop:
866
858
dict_load_column_low(
867
859
/*=================*/
868
860
        dict_table_t*   table,          /*!< in/out: table, could be NULL
869
 
                                        if we just populate a dict_column_t
 
861
                                        if we just polulate a dict_column_t
870
862
                                        struct with information from
871
863
                                        a SYS_COLUMNS record */
872
864
        mem_heap_t*     heap,           /*!< in/out: memory heap
873
865
                                        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 */
 
866
        dict_col_t*     column,         /*!< out: dict_column_t to fill */
 
867
        dulint*         table_id,       /*!< out: table id */
877
868
        const char**    col_name,       /*!< out: column name */
878
869
        const rec_t*    rec)            /*!< in: SYS_COLUMNS record */
879
870
{
885
876
        ulint           col_len;
886
877
        ulint           pos = 0;
887
878
 
888
 
        ut_ad(table || column);
889
 
 
890
879
        if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
891
880
                return("delete-marked record in SYS_COLUMNS");
892
881
        }
903
892
 
904
893
        if (table_id) {
905
894
                *table_id = mach_read_from_8(field);
906
 
        } else if (UNIV_UNLIKELY(table->id != mach_read_from_8(field))) {
 
895
        } else if (UNIV_UNLIKELY(ut_dulint_cmp(table->id,
 
896
                                 mach_read_from_8(field)))) {
907
897
                return("SYS_COLUMNS.TABLE_ID mismatch");
908
898
        }
909
899
 
913
903
                goto err_len;
914
904
        }
915
905
 
916
 
        pos = mach_read_from_4(field);
917
 
 
918
 
        if (UNIV_UNLIKELY(table && table->n_def != pos)) {
 
906
        if (!table) {
 
907
                pos = mach_read_from_4(field);
 
908
        } else if (UNIV_UNLIKELY(table->n_def != mach_read_from_4(field))) {
919
909
                return("SYS_COLUMNS.POS mismatch");
920
910
        }
921
911
 
1028
1018
        tuple = dtuple_create(heap, 1);
1029
1019
        dfield = dtuple_get_nth_field(tuple, 0);
1030
1020
 
1031
 
        buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
 
1021
        buf = mem_heap_alloc(heap, 8);
1032
1022
        mach_write_to_8(buf, table->id);
1033
1023
 
1034
1024
        dfield_set_data(dfield, buf, 8);
1212
1202
        tuple = dtuple_create(heap, 1);
1213
1203
        dfield = dtuple_get_nth_field(tuple, 0);
1214
1204
 
1215
 
        buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
 
1205
        buf = mem_heap_alloc(heap, 8);
1216
1206
        mach_write_to_8(buf, index->id);
1217
1207
 
1218
1208
        dfield_set_data(dfield, buf, 8);
1259
1249
 
1260
1250
/********************************************************************//**
1261
1251
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 */
 
1252
If "cached" is set to "TRUE", we will create a dict_index_t structure
 
1253
and fill it accordingly. Otherwise, the dict_index_t will
 
1254
be supplied by the caller and filled with information read from
 
1255
the record.
 
1256
@return error message, or NULL on success */
1266
1257
UNIV_INTERN
1267
1258
const char*
1268
1259
dict_load_index_low(
1269
1260
/*================*/
1270
1261
        byte*           table_id,       /*!< in/out: table id (8 bytes),
1271
 
                                        an "in" value if allocate=TRUE
1272
 
                                        and "out" when allocate=FALSE */
 
1262
                                        an "in" value if cached=TRUE
 
1263
                                        and "out" when cached=FALSE */
1273
1264
        const char*     table_name,     /*!< in: table name */
1274
1265
        mem_heap_t*     heap,           /*!< in/out: temporary memory heap */
1275
1266
        const rec_t*    rec,            /*!< in: SYS_INDEXES record */
1276
 
        ibool           allocate,       /*!< in: TRUE=allocate *index,
1277
 
                                        FALSE=fill in a pre-allocated
1278
 
                                        *index */
 
1267
        ibool           cached,         /*!< in: TRUE = add to cache,
 
1268
                                        FALSE = do not */
1279
1269
        dict_index_t**  index)          /*!< out,own: index, or NULL */
1280
1270
{
1281
1271
        const byte*     field;
1282
1272
        ulint           len;
1283
1273
        ulint           name_len;
1284
1274
        char*           name_buf;
1285
 
        index_id_t      id;
 
1275
        dulint          id;
1286
1276
        ulint           n_fields;
1287
1277
        ulint           type;
1288
1278
        ulint           space;
1289
1279
 
1290
 
        if (allocate) {
1291
 
                /* If allocate=TRUE, no dict_index_t will
 
1280
        if (cached) {
 
1281
                /* If "cached" is set to TRUE, no dict_index_t will
1292
1282
                be supplied. Initialize "*index" to NULL */
1293
1283
                *index = NULL;
1294
1284
        }
1307
1297
                return("incorrect column length in SYS_INDEXES");
1308
1298
        }
1309
1299
 
1310
 
        if (!allocate) {
 
1300
        if (!cached) {
1311
1301
                /* We are reading a SYS_INDEXES record. Copy the table_id */
1312
1302
                memcpy(table_id, (const char*)field, 8);
1313
1303
        } else if (memcmp(field, table_id, 8)) {
1363
1353
                goto err_len;
1364
1354
        }
1365
1355
 
1366
 
        if (allocate) {
 
1356
        if (cached) {
1367
1357
                *index = dict_mem_index_create(table_name, name_buf,
1368
1358
                                               space, type, n_fields);
1369
1359
        } else {
1399
1389
        dfield_t*       dfield;
1400
1390
        const rec_t*    rec;
1401
1391
        byte*           buf;
 
1392
        ibool           is_sys_table;
1402
1393
        mtr_t           mtr;
1403
1394
        ulint           error = DB_SUCCESS;
1404
1395
 
1405
1396
        ut_ad(mutex_own(&(dict_sys->mutex)));
1406
1397
 
 
1398
        if ((ut_dulint_get_high(table->id) == 0)
 
1399
            && (ut_dulint_get_low(table->id) < DICT_HDR_FIRST_ID)) {
 
1400
                is_sys_table = TRUE;
 
1401
        } else {
 
1402
                is_sys_table = FALSE;
 
1403
        }
 
1404
 
1407
1405
        mtr_start(&mtr);
1408
1406
 
1409
1407
        sys_indexes = dict_table_get_low("SYS_INDEXES");
1415
1413
        tuple = dtuple_create(heap, 1);
1416
1414
        dfield = dtuple_get_nth_field(tuple, 0);
1417
1415
 
1418
 
        buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
 
1416
        buf = mem_heap_alloc(heap, 8);
1419
1417
        mach_write_to_8(buf, table->id);
1420
1418
 
1421
1419
        dfield_set_data(dfield, buf, 8);
1489
1487
                              " is not clustered!\n", stderr);
1490
1488
 
1491
1489
                        goto corrupted;
1492
 
                } else if (table->id < DICT_HDR_FIRST_ID
 
1490
                } else if (is_sys_table
1493
1491
                           && (dict_index_is_clust(index)
1494
1492
                               || ((table == dict_sys->sys_tables)
1495
1493
                                   && !strcmp("ID_IND", index->name)))) {
1641
1639
 
1642
1640
                flags2 = mach_read_from_4(field);
1643
1641
 
1644
 
                if (flags2 & (SIZE_MAX << (DICT_TF2_BITS - DICT_TF2_SHIFT))) {
 
1642
                if (flags2 & (~0 << (DICT_TF2_BITS - DICT_TF2_SHIFT))) {
1645
1643
                        ut_print_timestamp(stderr);
1646
1644
                        fputs("  InnoDB: Warning: table ", stderr);
1647
1645
                        ut_print_filename(stderr, name);
1802
1800
 
1803
1801
        err = dict_load_indexes(table, heap);
1804
1802
 
1805
 
        /* Initialize table foreign_child value. Its value could be
1806
 
        changed when dict_load_foreigns() is called below */
1807
 
        table->fk_max_recusive_level = 0;
1808
 
 
1809
1803
        /* If the force recovery flag is set, we open the table irrespective
1810
1804
        of the error condition, since the user may want to dump data from the
1811
1805
        clustered index. However we load the foreign key information only if
1812
1806
        all indexes were loaded. */
1813
1807
        if (!cached) {
1814
1808
        } 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
 
                }
 
1809
                err = dict_load_foreigns(table->name, TRUE);
1823
1810
        } else if (!srv_force_recovery) {
1824
1811
                dict_table_remove_from_cache(table);
1825
1812
                table = NULL;
1860
1847
dict_table_t*
1861
1848
dict_load_table_on_id(
1862
1849
/*==================*/
1863
 
        table_id_t      table_id)       /*!< in: table id */
 
1850
        dulint  table_id)       /*!< in: table id */
1864
1851
{
1865
1852
        byte            id_buf[8];
1866
1853
        btr_pcur_t      pcur;
1877
1864
 
1878
1865
        ut_ad(mutex_own(&(dict_sys->mutex)));
1879
1866
 
1880
 
        table = NULL;
1881
 
 
1882
1867
        /* NOTE that the operation of this function is protected by
1883
1868
        the dictionary mutex, and therefore no deadlocks can occur
1884
1869
        with other dictionary operations. */
1905
1890
                                  BTR_SEARCH_LEAF, &pcur, &mtr);
1906
1891
        rec = btr_pcur_get_rec(&pcur);
1907
1892
 
1908
 
        if (!btr_pcur_is_on_user_rec(&pcur)) {
 
1893
        if (!btr_pcur_is_on_user_rec(&pcur)
 
1894
            || rec_get_deleted_flag(rec, 0)) {
1909
1895
                /* 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);
 
1896
 
 
1897
                btr_pcur_close(&pcur);
 
1898
                mtr_commit(&mtr);
 
1899
                mem_heap_free(heap);
 
1900
 
 
1901
                return(NULL);
1919
1902
        }
1920
1903
 
1921
1904
        /*---------------------------------------------------*/
1927
1910
        ut_ad(len == 8);
1928
1911
 
1929
1912
        /* 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;
 
1913
        if (ut_dulint_cmp(table_id, mach_read_from_8(field)) != 0) {
 
1914
 
 
1915
                btr_pcur_close(&pcur);
 
1916
                mtr_commit(&mtr);
 
1917
                mem_heap_free(heap);
 
1918
 
 
1919
                return(NULL);
1932
1920
        }
1933
1921
 
1934
1922
        /* Now we get the table name from the record */
1936
1924
        /* Load the table definition to memory */
1937
1925
        table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len),
1938
1926
                                TRUE);
1939
 
func_exit:
 
1927
 
1940
1928
        btr_pcur_close(&pcur);
1941
1929
        mtr_commit(&mtr);
1942
1930
        mem_heap_free(heap);
1988
1976
 
1989
1977
        ut_ad(mutex_own(&(dict_sys->mutex)));
1990
1978
 
1991
 
        foreign->foreign_col_names = static_cast<const char **>(mem_heap_alloc(
1992
 
                foreign->heap, foreign->n_fields * sizeof(void*)));
 
1979
        foreign->foreign_col_names = mem_heap_alloc(
 
1980
                foreign->heap, foreign->n_fields * sizeof(void*));
1993
1981
 
1994
 
        foreign->referenced_col_names = static_cast<const char **>(mem_heap_alloc(
1995
 
                foreign->heap, foreign->n_fields * sizeof(void*)));
 
1982
        foreign->referenced_col_names = mem_heap_alloc(
 
1983
                foreign->heap, foreign->n_fields * sizeof(void*));
1996
1984
        mtr_start(&mtr);
1997
1985
 
1998
1986
        sys_foreign_cols = dict_table_get_low("SYS_FOREIGN_COLS");
2046
2034
/*==============*/
2047
2035
        const char*     id,     /*!< in: foreign constraint id as a
2048
2036
                                null-terminated string */
2049
 
        ibool           check_charsets,
 
2037
        ibool           check_charsets)
2050
2038
                                /*!< in: TRUE=check charset compatibility */
2051
 
        ibool           check_recursive)
2052
 
                                /*!< in: Whether to record the foreign table
2053
 
                                parent count to avoid unlimited recursive
2054
 
                                load of chained foreign tables */
2055
2039
{
2056
2040
        dict_foreign_t* foreign;
2057
2041
        dict_table_t*   sys_foreign;
2065
2049
        ulint           len;
2066
2050
        ulint           n_fields_and_type;
2067
2051
        mtr_t           mtr;
2068
 
        dict_table_t*   for_table;
2069
 
        dict_table_t*   ref_table;
2070
2052
 
2071
2053
        ut_ad(mutex_own(&(dict_sys->mutex)));
2072
2054
 
2151
2133
 
2152
2134
        dict_load_foreign_cols(id, foreign);
2153
2135
 
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
 
        }
 
2136
        /* If the foreign table is not yet in the dictionary cache, we
 
2137
        have to load it so that we are able to make type comparisons
 
2138
        in the next function call. */
 
2139
 
 
2140
        dict_table_get_low(foreign->foreign_table_name);
2202
2141
 
2203
2142
        /* Note that there may already be a foreign constraint object in
2204
2143
        the dictionary cache for this constraint: then the following
2223
2162
dict_load_foreigns(
2224
2163
/*===============*/
2225
2164
        const char*     table_name,     /*!< in: table name */
2226
 
        ibool           check_recursive,/*!< in: Whether to check recursive
2227
 
                                        load of tables chained by FK */
2228
2165
        ibool           check_charsets) /*!< in: TRUE=check charset
2229
2166
                                        compatibility */
2230
2167
{
2295
2232
 
2296
2233
        if (0 != cmp_data_data(dfield_get_type(dfield)->mtype,
2297
2234
                               dfield_get_type(dfield)->prtype,
2298
 
                               static_cast<const unsigned char *>(dfield_get_data(dfield)),
2299
 
                               dfield_get_len(dfield),
 
2235
                               dfield_get_data(dfield), dfield_get_len(dfield),
2300
2236
                               field, len)) {
2301
2237
 
2302
2238
                goto load_next_index;
2327
2263
 
2328
2264
        /* Load the foreign constraint definition to the dictionary cache */
2329
2265
 
2330
 
        err = dict_load_foreign(id, check_charsets, check_recursive);
 
2266
        err = dict_load_foreign(id, check_charsets);
2331
2267
 
2332
2268
        if (err != DB_SUCCESS) {
2333
2269
                btr_pcur_close(&pcur);
2355
2291
 
2356
2292
                mtr_start(&mtr);
2357
2293
 
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
2294
                goto start_load;
2364
2295
        }
2365
2296