~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2010-12-08 22:35:56 UTC
  • mfrom: (1819.9.158 update-innobase)
  • Revision ID: brian@tangent.org-20101208223556-37mi4omqg7lkjzf3
Merge in Stewart's changes, 1.3 changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1799
1799
 
1800
1800
        err = dict_load_indexes(table, heap);
1801
1801
 
 
1802
        /* Initialize table foreign_child value. Its value could be
 
1803
        changed when dict_load_foreigns() is called below */
 
1804
        table->fk_max_recusive_level = 0;
 
1805
 
1802
1806
        /* If the force recovery flag is set, we open the table irrespective
1803
1807
        of the error condition, since the user may want to dump data from the
1804
1808
        clustered index. However we load the foreign key information only if
1805
1809
        all indexes were loaded. */
1806
1810
        if (!cached) {
1807
1811
        } else if (err == DB_SUCCESS) {
1808
 
                err = dict_load_foreigns(table->name, TRUE);
 
1812
                err = dict_load_foreigns(table->name, TRUE, TRUE);
 
1813
 
 
1814
                if (err != DB_SUCCESS) {
 
1815
                        dict_table_remove_from_cache(table);
 
1816
                        table = NULL;
 
1817
                }
1809
1818
        } else if (!srv_force_recovery) {
1810
1819
                dict_table_remove_from_cache(table);
1811
1820
                table = NULL;
1812
1821
        }
 
1822
 
 
1823
        table->fk_max_recusive_level = 0;
1813
1824
#if 0
1814
1825
        if (err != DB_SUCCESS && table != NULL) {
1815
1826
 
1863
1874
 
1864
1875
        ut_ad(mutex_own(&(dict_sys->mutex)));
1865
1876
 
 
1877
        table = NULL;
 
1878
 
1866
1879
        /* NOTE that the operation of this function is protected by
1867
1880
        the dictionary mutex, and therefore no deadlocks can occur
1868
1881
        with other dictionary operations. */
1889
1902
                                  BTR_SEARCH_LEAF, &pcur, &mtr);
1890
1903
        rec = btr_pcur_get_rec(&pcur);
1891
1904
 
1892
 
        if (!btr_pcur_is_on_user_rec(&pcur)
1893
 
            || rec_get_deleted_flag(rec, 0)) {
 
1905
        if (!btr_pcur_is_on_user_rec(&pcur)) {
1894
1906
                /* Not found */
1895
 
 
1896
 
                btr_pcur_close(&pcur);
1897
 
                mtr_commit(&mtr);
1898
 
                mem_heap_free(heap);
1899
 
 
1900
 
                return(NULL);
 
1907
                goto func_exit;
 
1908
        }
 
1909
 
 
1910
        /* Find the first record that is not delete marked */
 
1911
        while (rec_get_deleted_flag(rec, 0)) {
 
1912
                if (!btr_pcur_move_to_next_user_rec(&pcur, &mtr)) {
 
1913
                        goto func_exit;
 
1914
                }
 
1915
                rec = btr_pcur_get_rec(&pcur);
1901
1916
        }
1902
1917
 
1903
1918
        /*---------------------------------------------------*/
1910
1925
 
1911
1926
        /* Check if the table id in record is the one searched for */
1912
1927
        if (table_id != mach_read_from_8(field)) {
1913
 
 
1914
 
                btr_pcur_close(&pcur);
1915
 
                mtr_commit(&mtr);
1916
 
                mem_heap_free(heap);
1917
 
 
1918
 
                return(NULL);
 
1928
                goto func_exit;
1919
1929
        }
1920
1930
 
1921
1931
        /* Now we get the table name from the record */
1923
1933
        /* Load the table definition to memory */
1924
1934
        table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len),
1925
1935
                                TRUE);
1926
 
 
 
1936
func_exit:
1927
1937
        btr_pcur_close(&pcur);
1928
1938
        mtr_commit(&mtr);
1929
1939
        mem_heap_free(heap);
2033
2043
/*==============*/
2034
2044
        const char*     id,     /*!< in: foreign constraint id as a
2035
2045
                                null-terminated string */
2036
 
        ibool           check_charsets)
 
2046
        ibool           check_charsets,
2037
2047
                                /*!< in: TRUE=check charset compatibility */
 
2048
        ibool           check_recursive)
 
2049
                                /*!< in: Whether to record the foreign table
 
2050
                                parent count to avoid unlimited recursive
 
2051
                                load of chained foreign tables */
2038
2052
{
2039
2053
        dict_foreign_t* foreign;
2040
2054
        dict_table_t*   sys_foreign;
2048
2062
        ulint           len;
2049
2063
        ulint           n_fields_and_type;
2050
2064
        mtr_t           mtr;
 
2065
        dict_table_t*   for_table;
 
2066
        dict_table_t*   ref_table;
2051
2067
 
2052
2068
        ut_ad(mutex_own(&(dict_sys->mutex)));
2053
2069
 
2132
2148
 
2133
2149
        dict_load_foreign_cols(id, foreign);
2134
2150
 
2135
 
        /* If the foreign table is not yet in the dictionary cache, we
2136
 
        have to load it so that we are able to make type comparisons
2137
 
        in the next function call. */
2138
 
 
2139
 
        dict_table_get_low(foreign->foreign_table_name);
 
2151
        ref_table = dict_table_check_if_in_cache_low(
 
2152
                        foreign->referenced_table_name);
 
2153
 
 
2154
        /* We could possibly wind up in a deep recursive calls if
 
2155
        we call dict_table_get_low() again here if there
 
2156
        is a chain of tables concatenated together with
 
2157
        foreign constraints. In such case, each table is
 
2158
        both a parent and child of the other tables, and
 
2159
        act as a "link" in such table chains.
 
2160
        To avoid such scenario, we would need to check the
 
2161
        number of ancesters the current table has. If that
 
2162
        exceeds DICT_FK_MAX_CHAIN_LEN, we will stop loading
 
2163
        the child table.
 
2164
        Foreign constraints are loaded in a Breath First fashion,
 
2165
        that is, the index on FOR_NAME is scanned first, and then
 
2166
        index on REF_NAME. So foreign constrains in which
 
2167
        current table is a child (foreign table) are loaded first,
 
2168
        and then those constraints where current table is a
 
2169
        parent (referenced) table.
 
2170
        Thus we could check the parent (ref_table) table's
 
2171
        reference count (fk_max_recusive_level) to know how deep the
 
2172
        recursive call is. If the parent table (ref_table) is already
 
2173
        loaded, and its fk_max_recusive_level is larger than
 
2174
        DICT_FK_MAX_CHAIN_LEN, we will stop the recursive loading
 
2175
        by skipping loading the child table. It will not affect foreign
 
2176
        constraint check for DMLs since child table will be loaded
 
2177
        at that time for the constraint check. */
 
2178
        if (!ref_table
 
2179
            || ref_table->fk_max_recusive_level < DICT_FK_MAX_RECURSIVE_LOAD) {
 
2180
 
 
2181
                /* If the foreign table is not yet in the dictionary cache, we
 
2182
                have to load it so that we are able to make type comparisons
 
2183
                in the next function call. */
 
2184
 
 
2185
                for_table = dict_table_get_low(foreign->foreign_table_name);
 
2186
 
 
2187
                if (for_table && ref_table && check_recursive) {
 
2188
                        /* This is to record the longest chain of ancesters
 
2189
                        this table has, if the parent has more ancesters
 
2190
                        than this table has, record it after add 1 (for this
 
2191
                        parent */
 
2192
                        if (ref_table->fk_max_recusive_level
 
2193
                            >= for_table->fk_max_recusive_level) {
 
2194
                                for_table->fk_max_recusive_level =
 
2195
                                         ref_table->fk_max_recusive_level + 1;
 
2196
                        }
 
2197
                }
 
2198
        }
2140
2199
 
2141
2200
        /* Note that there may already be a foreign constraint object in
2142
2201
        the dictionary cache for this constraint: then the following
2161
2220
dict_load_foreigns(
2162
2221
/*===============*/
2163
2222
        const char*     table_name,     /*!< in: table name */
 
2223
        ibool           check_recursive,/*!< in: Whether to check recursive
 
2224
                                        load of tables chained by FK */
2164
2225
        ibool           check_charsets) /*!< in: TRUE=check charset
2165
2226
                                        compatibility */
2166
2227
{
2262
2323
 
2263
2324
        /* Load the foreign constraint definition to the dictionary cache */
2264
2325
 
2265
 
        err = dict_load_foreign(id, check_charsets);
 
2326
        err = dict_load_foreign(id, check_charsets, check_recursive);
2266
2327
 
2267
2328
        if (err != DB_SUCCESS) {
2268
2329
                btr_pcur_close(&pcur);
2290
2351
 
2291
2352
                mtr_start(&mtr);
2292
2353
 
 
2354
                /* Switch to scan index on REF_NAME, fk_max_recusive_level
 
2355
                already been updated when scanning FOR_NAME index, no need to
 
2356
                update again */
 
2357
                check_recursive = FALSE;
 
2358
 
2293
2359
                goto start_load;
2294
2360
        }
2295
2361