~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

Merge Joe, plus I updated the tests.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (C) 1996, 2010, Innobase Oy. All Rights Reserved.
 
3
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
4
4
 
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
11
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
12
 
13
13
You should have received a copy of the GNU General Public License along with
14
 
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
 
St, Fifth Floor, Boston, MA 02110-1301 USA
 
14
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
15
Place, Suite 330, Boston, MA 02111-1307 USA
16
16
 
17
17
*****************************************************************************/
18
18
 
56
56
 
57
57
#include <ctype.h>
58
58
 
59
 
#include <drizzled/session.h>
60
 
 
61
59
/** the dictionary system */
62
60
UNIV_INTERN dict_sys_t* dict_sys        = NULL;
63
61
 
71
69
on the mode in trx_struct::dict_operation_lock_mode */
72
70
UNIV_INTERN rw_lock_t   dict_operation_lock;
73
71
 
74
 
/* Keys to register rwlocks and mutexes with performance schema */
75
 
#ifdef UNIV_PFS_RWLOCK
76
 
UNIV_INTERN mysql_pfs_key_t     dict_operation_lock_key;
77
 
UNIV_INTERN mysql_pfs_key_t     index_tree_rw_lock_key;
78
 
#endif /* UNIV_PFS_RWLOCK */
79
 
 
80
 
#ifdef UNIV_PFS_MUTEX
81
 
UNIV_INTERN mysql_pfs_key_t     dict_sys_mutex_key;
82
 
UNIV_INTERN mysql_pfs_key_t     dict_foreign_err_mutex_key;
83
 
#endif /* UNIV_PFS_MUTEX */
84
 
 
85
72
#define DICT_HEAP_SIZE          100     /*!< initial memory heap size when
86
73
                                        creating a table or index object */
87
74
#define DICT_POOL_PER_TABLE_HASH 512    /*!< buffer pool max size per table
92
79
/** Identifies generated InnoDB foreign key names */
93
80
static char     dict_ibfk[] = "_ibfk_";
94
81
 
95
 
/** array of rw locks protecting
96
 
dict_table_t::stat_initialized
97
 
dict_table_t::stat_n_rows (*)
98
 
dict_table_t::stat_clustered_index_size
99
 
dict_table_t::stat_sum_of_other_index_sizes
100
 
dict_table_t::stat_modified_counter (*)
101
 
dict_table_t::indexes*::stat_n_diff_key_vals[]
102
 
dict_table_t::indexes*::stat_index_size
103
 
dict_table_t::indexes*::stat_n_leaf_pages
104
 
(*) those are not always protected for performance reasons */
105
 
#define DICT_TABLE_STATS_LATCHES_SIZE   64
106
 
static rw_lock_t        dict_table_stats_latches[DICT_TABLE_STATS_LATCHES_SIZE];
107
 
 
108
82
/*******************************************************************//**
109
83
Tries to find column names for the index and sets the col field of the
110
 
index.
111
 
@return TRUE if the column names were found */
 
84
index. */
112
85
static
113
 
ibool
 
86
void
114
87
dict_index_find_cols(
115
88
/*=================*/
116
89
        dict_table_t*   table,  /*!< in: table */
165
138
void
166
139
dict_field_print_low(
167
140
/*=================*/
168
 
        const dict_field_t*     field); /*!< in: field */
 
141
        dict_field_t*   field); /*!< in: field */
169
142
/*********************************************************************//**
170
143
Frees a foreign key struct. */
171
144
static
264
237
        mutex_exit(&(dict_sys->mutex));
265
238
}
266
239
 
267
 
/** Get the latch that protects the stats of a given table */
268
 
#define GET_TABLE_STATS_LATCH(table) \
269
 
        (&dict_table_stats_latches[ut_fold_ull(table->id) \
270
 
                                   % DICT_TABLE_STATS_LATCHES_SIZE])
271
 
 
272
 
/**********************************************************************//**
273
 
Lock the appropriate latch to protect a given table's statistics.
274
 
table->id is used to pick the corresponding latch from a global array of
275
 
latches. */
276
 
UNIV_INTERN
277
 
void
278
 
dict_table_stats_lock(
279
 
/*==================*/
280
 
        const dict_table_t*     table,          /*!< in: table */
281
 
        ulint                   latch_mode)     /*!< in: RW_S_LATCH or
282
 
                                                RW_X_LATCH */
283
 
{
284
 
        ut_ad(table != NULL);
285
 
        ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
286
 
 
287
 
        switch (latch_mode) {
288
 
        case RW_S_LATCH:
289
 
                rw_lock_s_lock(GET_TABLE_STATS_LATCH(table));
290
 
                break;
291
 
        case RW_X_LATCH:
292
 
                rw_lock_x_lock(GET_TABLE_STATS_LATCH(table));
293
 
                break;
294
 
        case RW_NO_LATCH:
295
 
                /* fall through */
296
 
        default:
297
 
                ut_error;
298
 
        }
299
 
}
300
 
 
301
 
/**********************************************************************//**
302
 
Unlock the latch that has been locked by dict_table_stats_lock() */
303
 
UNIV_INTERN
304
 
void
305
 
dict_table_stats_unlock(
306
 
/*====================*/
307
 
        const dict_table_t*     table,          /*!< in: table */
308
 
        ulint                   latch_mode)     /*!< in: RW_S_LATCH or
309
 
                                                RW_X_LATCH */
310
 
{
311
 
        ut_ad(table != NULL);
312
 
        ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
313
 
 
314
 
        switch (latch_mode) {
315
 
        case RW_S_LATCH:
316
 
                rw_lock_s_unlock(GET_TABLE_STATS_LATCH(table));
317
 
                break;
318
 
        case RW_X_LATCH:
319
 
                rw_lock_x_unlock(GET_TABLE_STATS_LATCH(table));
320
 
                break;
321
 
        case RW_NO_LATCH:
322
 
                /* fall through */
323
 
        default:
324
 
                ut_error;
325
 
        }
326
 
}
327
 
 
328
240
/********************************************************************//**
329
241
Decrements the count of open MySQL handles to a table. */
330
242
UNIV_INTERN
457
369
dict_index_get_on_id_low(
458
370
/*=====================*/
459
371
        dict_table_t*   table,  /*!< in: table */
460
 
        index_id_t      id)     /*!< in: index id */
 
372
        dulint          id)     /*!< in: index id */
461
373
{
462
374
        dict_index_t*   index;
463
375
 
464
376
        index = dict_table_get_first_index(table);
465
377
 
466
378
        while (index) {
467
 
                if (id == index->id) {
 
379
                if (0 == ut_dulint_cmp(id, index->id)) {
468
380
                        /* Found */
469
381
 
470
382
                        return(index);
606
518
dict_table_t*
607
519
dict_table_get_on_id(
608
520
/*=================*/
609
 
        table_id_t      table_id,       /*!< in: table id */
610
 
        trx_t*          trx)            /*!< in: transaction handle */
 
521
        dulint  table_id,       /*!< in: table id */
 
522
        trx_t*  trx)            /*!< in: transaction handle */
611
523
{
612
524
        dict_table_t*   table;
613
525
 
614
 
        if (trx->dict_operation_lock_mode == RW_X_LATCH) {
615
 
 
616
 
                /* Note: An X latch implies that the transaction
617
 
                already owns the dictionary mutex. */
618
 
 
619
 
                ut_ad(mutex_own(&dict_sys->mutex));
 
526
        if (ut_dulint_cmp(table_id, DICT_FIELDS_ID) <= 0
 
527
            || trx->dict_operation_lock_mode == RW_X_LATCH) {
 
528
                /* It is a system table which will always exist in the table
 
529
                cache: we avoid acquiring the dictionary mutex, because
 
530
                if we are doing a rollback to handle an error in TABLE
 
531
                CREATE, for example, we already have the mutex! */
 
532
 
 
533
                ut_ad(mutex_own(&(dict_sys->mutex))
 
534
                      || trx->dict_operation_lock_mode == RW_X_LATCH);
620
535
 
621
536
                return(dict_table_get_on_id_low(table_id));
622
537
        }
688
603
dict_init(void)
689
604
/*===========*/
690
605
{
691
 
        int     i;
692
 
 
693
 
        dict_sys = static_cast<dict_sys_t *>(mem_alloc(sizeof(dict_sys_t)));
694
 
 
695
 
        mutex_create(dict_sys_mutex_key, &dict_sys->mutex, SYNC_DICT);
 
606
        dict_sys = mem_alloc(sizeof(dict_sys_t));
 
607
 
 
608
        mutex_create(&dict_sys->mutex, SYNC_DICT);
696
609
 
697
610
        dict_sys->table_hash = hash_create(buf_pool_get_curr_size()
698
611
                                           / (DICT_POOL_PER_TABLE_HASH
704
617
 
705
618
        UT_LIST_INIT(dict_sys->table_LRU);
706
619
 
707
 
        rw_lock_create(dict_operation_lock_key,
708
 
                       &dict_operation_lock, SYNC_DICT_OPERATION);
 
620
        rw_lock_create(&dict_operation_lock, SYNC_DICT_OPERATION);
709
621
 
710
622
        dict_foreign_err_file = os_file_create_tmpfile();
711
623
        ut_a(dict_foreign_err_file);
712
624
 
713
 
        mutex_create(dict_foreign_err_mutex_key,
714
 
                     &dict_foreign_err_mutex, SYNC_ANY_LATCH);
715
 
 
716
 
        for (i = 0; i < DICT_TABLE_STATS_LATCHES_SIZE; i++) {
717
 
                rw_lock_create(PFS_NOT_INSTRUMENTED,
718
 
                               &dict_table_stats_latches[i], SYNC_INDEX_TREE);
719
 
        }
 
625
        mutex_create(&dict_foreign_err_mutex, SYNC_ANY_LATCH);
720
626
}
721
627
 
722
628
/**********************************************************************//**
746
652
        mutex_exit(&(dict_sys->mutex));
747
653
 
748
654
        if (table != NULL) {
749
 
                /* If table->ibd_file_missing == TRUE, this will
750
 
                print an error message and return without doing
751
 
                anything. */
752
 
                dict_update_statistics(table, TRUE /* only update stats
753
 
                                       if they have not been initialized */);
 
655
                if (!table->stat_initialized) {
 
656
                        /* If table->ibd_file_missing == TRUE, this will
 
657
                        print an error message and return without doing
 
658
                        anything. */
 
659
                        dict_update_statistics(table);
 
660
                }
754
661
        }
755
662
 
756
663
        return(table);
828
735
        table->cached = TRUE;
829
736
 
830
737
        fold = ut_fold_string(table->name);
831
 
        id_fold = ut_fold_ull(table->id);
 
738
        id_fold = ut_fold_dulint(table->id);
832
739
 
833
740
        row_len = 0;
834
741
        for (i = 0; i < table->n_def; i++) {
870
777
                dict_table_t*   table2;
871
778
                HASH_SEARCH(id_hash, dict_sys->table_id_hash, id_fold,
872
779
                            dict_table_t*, table2, ut_ad(table2->cached),
873
 
                            table2->id == table->id);
 
780
                            ut_dulint_cmp(table2->id, table->id) == 0);
874
781
                ut_a(table2 == NULL);
875
782
 
876
783
#ifdef UNIV_DEBUG
892
799
        /* Add table to LRU list of tables */
893
800
        UT_LIST_ADD_FIRST(table_LRU, dict_sys->table_LRU, table);
894
801
 
895
 
        dict_sys->size += mem_heap_get_size(table->heap)
896
 
                + strlen(table->name) + 1;
 
802
        dict_sys->size += mem_heap_get_size(table->heap);
897
803
}
898
804
 
899
805
/**********************************************************************//**
905
811
dict_index_t*
906
812
dict_index_find_on_id_low(
907
813
/*======================*/
908
 
        index_id_t      id)     /*!< in: index id */
 
814
        dulint  id)     /*!< in: index id */
909
815
{
910
816
        dict_table_t*   table;
911
817
        dict_index_t*   index;
916
822
                index = dict_table_get_first_index(table);
917
823
 
918
824
                while (index) {
919
 
                        if (id == index->id) {
 
825
                        if (0 == ut_dulint_cmp(id, index->id)) {
920
826
                                /* Found */
921
827
 
922
828
                                return(index);
947
853
        dict_foreign_t* foreign;
948
854
        dict_index_t*   index;
949
855
        ulint           fold;
950
 
        char            old_name[MAX_TABLE_NAME_LEN + 1];
 
856
        ulint           old_size;
 
857
        const char*     old_name;
951
858
 
952
859
        ut_ad(table);
953
860
        ut_ad(mutex_own(&(dict_sys->mutex)));
954
861
 
955
 
        /* store the old/current name to an automatic variable */
956
 
        if (strlen(table->name) + 1 <= sizeof(old_name)) {
957
 
                memcpy(old_name, table->name, strlen(table->name) + 1);
958
 
        } else {
959
 
                ut_print_timestamp(stderr);
960
 
                fprintf(stderr, "InnoDB: too long table name: '%s', "
961
 
                        "max length is %d\n", table->name,
962
 
                        MAX_TABLE_NAME_LEN);
963
 
                ut_error;
964
 
        }
 
862
        old_size = mem_heap_get_size(table->heap);
 
863
        old_name = table->name;
965
864
 
966
865
        fold = ut_fold_string(new_name);
967
866
 
1007
906
        /* Remove table from the hash tables of tables */
1008
907
        HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash,
1009
908
                    ut_fold_string(old_name), table);
1010
 
 
1011
 
        if (strlen(new_name) > strlen(table->name)) {
1012
 
                /* We allocate MAX_TABLE_NAME_LEN+1 bytes here to avoid
1013
 
                memory fragmentation, we assume a repeated calls of
1014
 
                ut_realloc() with the same size do not cause fragmentation */
1015
 
                ut_a(strlen(new_name) <= MAX_TABLE_NAME_LEN);
1016
 
                table->name = static_cast<char *>(ut_realloc(table->name, MAX_TABLE_NAME_LEN + 1));
1017
 
        }
1018
 
        memcpy(table->name, new_name, strlen(new_name) + 1);
 
909
        table->name = mem_heap_strdup(table->heap, new_name);
1019
910
 
1020
911
        /* Add table to hash table of tables */
1021
912
        HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold,
1022
913
                    table);
1023
 
 
1024
 
        dict_sys->size += strlen(new_name) - strlen(old_name);
1025
 
        ut_a(dict_sys->size > 0);
 
914
        dict_sys->size += (mem_heap_get_size(table->heap) - old_size);
1026
915
 
1027
916
        /* Update the table_name field in indexes */
1028
917
        index = dict_table_get_first_index(table);
1081
970
                        TODO: store buf len to save memory */
1082
971
 
1083
972
                        foreign->foreign_table_name
1084
 
                                = static_cast<char *>(mem_heap_alloc(foreign->heap,
1085
 
                                                 ut_strlen(table->name) + 1));
 
973
                                = mem_heap_alloc(foreign->heap,
 
974
                                                 ut_strlen(table->name) + 1);
1086
975
                }
1087
976
 
1088
977
                strcpy(foreign->foreign_table_name, table->name);
1105
994
                                /* This is a generated >= 4.0.18 format id */
1106
995
 
1107
996
                                if (strlen(table->name) > strlen(old_name)) {
1108
 
                                        foreign->id = static_cast<char *>(mem_heap_alloc(
 
997
                                        foreign->id = mem_heap_alloc(
1109
998
                                                foreign->heap,
1110
999
                                                strlen(table->name)
1111
 
                                                + strlen(old_id) + 1));
 
1000
                                                + strlen(old_id) + 1);
1112
1001
                                }
1113
1002
 
1114
1003
                                /* Replace the prefix 'databasename/tablename'
1124
1013
                                if (dict_get_db_name_len(table->name)
1125
1014
                                    > dict_get_db_name_len(foreign->id)) {
1126
1015
 
1127
 
                                        foreign->id = static_cast<char *>(mem_heap_alloc(
 
1016
                                        foreign->id = mem_heap_alloc(
1128
1017
                                                foreign->heap,
1129
 
                                                db_len + strlen(old_id) + 1));
 
1018
                                                db_len + strlen(old_id) + 1);
1130
1019
                                }
1131
1020
 
1132
1021
                                /* Replace the database prefix in id with the
1152
1041
                        /* Allocate a longer name buffer;
1153
1042
                        TODO: store buf len to save memory */
1154
1043
 
1155
 
                        foreign->referenced_table_name = static_cast<char *>(mem_heap_alloc(
1156
 
                                foreign->heap, strlen(table->name) + 1));
 
1044
                        foreign->referenced_table_name = mem_heap_alloc(
 
1045
                                foreign->heap, strlen(table->name) + 1);
1157
1046
                }
1158
1047
 
1159
1048
                strcpy(foreign->referenced_table_name, table->name);
1172
1061
dict_table_change_id_in_cache(
1173
1062
/*==========================*/
1174
1063
        dict_table_t*   table,  /*!< in/out: table object already in cache */
1175
 
        table_id_t      new_id) /*!< in: new id to set */
 
1064
        dulint          new_id) /*!< in: new id to set */
1176
1065
{
1177
1066
        ut_ad(table);
1178
1067
        ut_ad(mutex_own(&(dict_sys->mutex)));
1181
1070
        /* Remove the table from the hash table of id's */
1182
1071
 
1183
1072
        HASH_DELETE(dict_table_t, id_hash, dict_sys->table_id_hash,
1184
 
                    ut_fold_ull(table->id), table);
 
1073
                    ut_fold_dulint(table->id), table);
1185
1074
        table->id = new_id;
1186
1075
 
1187
1076
        /* Add the table back to the hash table */
1188
1077
        HASH_INSERT(dict_table_t, id_hash, dict_sys->table_id_hash,
1189
 
                    ut_fold_ull(table->id), table);
 
1078
                    ut_fold_dulint(table->id), table);
1190
1079
}
1191
1080
 
1192
1081
/**********************************************************************//**
1242
1131
        HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash,
1243
1132
                    ut_fold_string(table->name), table);
1244
1133
        HASH_DELETE(dict_table_t, id_hash, dict_sys->table_id_hash,
1245
 
                    ut_fold_ull(table->id), table);
 
1134
                    ut_fold_dulint(table->id), table);
1246
1135
 
1247
1136
        /* Remove table from LRU list of tables */
1248
1137
        UT_LIST_REMOVE(table_LRU, dict_sys->table_LRU, table);
1249
1138
 
1250
 
        size = mem_heap_get_size(table->heap) + strlen(table->name) + 1;
 
1139
        size = mem_heap_get_size(table->heap);
1251
1140
 
1252
1141
        ut_ad(dict_sys->size >= size);
1253
1142
 
1279
1168
        ulint                   i;
1280
1169
 
1281
1170
        for (i = 0; i < UT_ARR_SIZE(reserved_names); i++) {
1282
 
                if (innobase_strcasecmp(name, reserved_names[i]) == 0) {
 
1171
                if (strcmp(name, reserved_names[i]) == 0) {
1283
1172
 
1284
1173
                        return(TRUE);
1285
1174
                }
1309
1198
                = TRX_UNDO_PAGE_HDR - TRX_UNDO_PAGE_HDR_SIZE
1310
1199
                + 2 /* next record pointer */
1311
1200
                + 1 /* type_cmpl */
1312
 
                + 11 /* trx->undo_no */ + 11 /* table->id */
 
1201
                + 11 /* trx->undo_no */ - 11 /* table->id */
1313
1202
                + 1 /* rec_get_info_bits() */
1314
1203
                + 11 /* DB_TRX_ID */
1315
1204
                + 11 /* DB_ROLL_PTR */
1541
1430
 
1542
1431
/**********************************************************************//**
1543
1432
Adds an index to the dictionary cache.
1544
 
@return DB_SUCCESS, DB_TOO_BIG_RECORD, or DB_CORRUPTION */
 
1433
@return DB_SUCCESS or DB_TOO_BIG_RECORD */
1545
1434
UNIV_INTERN
1546
1435
ulint
1547
1436
dict_index_add_to_cache(
1567
1456
        ut_a(!dict_index_is_clust(index)
1568
1457
             || UT_LIST_GET_LEN(table->indexes) == 0);
1569
1458
 
1570
 
        if (!dict_index_find_cols(table, index)) {
1571
 
 
1572
 
                dict_mem_index_free(index);
1573
 
                return(DB_CORRUPTION);
1574
 
        }
 
1459
        dict_index_find_cols(table, index);
1575
1460
 
1576
1461
        /* Build the cache internal representation of the index,
1577
1462
        containing also the added system fields */
1676
1561
        new_index->stat_n_leaf_pages = 1;
1677
1562
 
1678
1563
        new_index->page = page_no;
1679
 
        rw_lock_create(index_tree_rw_lock_key, &new_index->lock,
1680
 
                       SYNC_INDEX_TREE);
 
1564
        rw_lock_create(&new_index->lock, SYNC_INDEX_TREE);
1681
1565
 
1682
1566
        if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) {
1683
1567
 
1684
 
                new_index->stat_n_diff_key_vals = static_cast<ib_int64_t *>(mem_heap_alloc(
 
1568
                new_index->stat_n_diff_key_vals = mem_heap_alloc(
1685
1569
                        new_index->heap,
1686
1570
                        (1 + dict_index_get_n_unique(new_index))
1687
 
                        * sizeof(ib_int64_t)));
 
1571
                        * sizeof(ib_int64_t));
1688
1572
                /* Give some sensible values to stat_n_... in case we do
1689
1573
                not calculate statistics quickly enough */
1690
1574
 
1780
1664
 
1781
1665
/*******************************************************************//**
1782
1666
Tries to find column names for the index and sets the col field of the
1783
 
index.
1784
 
@return TRUE if the column names were found */
 
1667
index. */
1785
1668
static
1786
 
ibool
 
1669
void
1787
1670
dict_index_find_cols(
1788
1671
/*=================*/
1789
1672
        dict_table_t*   table,  /*!< in: table */
1808
1691
                        }
1809
1692
                }
1810
1693
 
1811
 
#ifdef UNIV_DEBUG
1812
1694
                /* It is an error not to find a matching column. */
1813
1695
                fputs("InnoDB: Error: no matching column for ", stderr);
1814
1696
                ut_print_name(stderr, NULL, FALSE, field->name);
1815
1697
                fputs(" in ", stderr);
1816
1698
                dict_index_name_print(stderr, NULL, index);
1817
1699
                fputs("!\n", stderr);
1818
 
#endif /* UNIV_DEBUG */
1819
 
                return(FALSE);
 
1700
                ut_error;
1820
1701
 
1821
1702
found:
1822
1703
                ;
1823
1704
        }
1824
 
 
1825
 
        return(TRUE);
1826
1705
}
1827
1706
#endif /* !UNIV_HOTBACKUP */
1828
1707
 
2065
1944
        }
2066
1945
 
2067
1946
        /* Remember the table columns already contained in new_index */
2068
 
        void *indexed_ptr= mem_zalloc(table->n_cols * sizeof *indexed);
2069
 
        indexed = static_cast<unsigned long *>(indexed_ptr);
 
1947
        indexed = mem_zalloc(table->n_cols * sizeof *indexed);
2070
1948
 
2071
1949
        /* Mark the table columns already contained in new_index */
2072
1950
        for (i = 0; i < new_index->n_def; i++) {
2150
2028
        dict_index_copy(new_index, index, table, 0, index->n_fields);
2151
2029
 
2152
2030
        /* Remember the table columns already contained in new_index */
2153
 
        void *indexed_ptr= mem_zalloc(table->n_cols * sizeof *indexed);
2154
 
        indexed = static_cast<unsigned long *>(indexed_ptr);
 
2031
        indexed = mem_zalloc(table->n_cols * sizeof *indexed);
2155
2032
 
2156
2033
        /* Mark the table columns already contained in new_index */
2157
2034
        for (i = 0; i < new_index->n_def; i++) {
2506
2383
                                /* We found a matching index, select
2507
2384
                                the index with the higher id*/
2508
2385
 
2509
 
                                if (!found || index->id > found->id) {
 
2386
                                if (!found
 
2387
                                    || ut_dulint_cmp(index->id, found->id) > 0) {
2510
2388
 
2511
2389
                                        found = index;
2512
2390
                                }
2842
2720
 
2843
2721
        if (quote) {
2844
2722
                char*   d;
2845
 
                str = d = static_cast<char *>(mem_heap_alloc(heap, len + 1));
 
2723
                str = d = mem_heap_alloc(heap, len + 1);
2846
2724
                while (len--) {
2847
2725
                        if ((*d++ = *s++) == quote) {
2848
2726
                                s++;
2861
2739
                /* Convert the identifier from connection character set
2862
2740
                to UTF-8. */
2863
2741
                len = 3 * len + 1;
2864
 
                *id = dst = static_cast<char *>(mem_heap_alloc(heap, len));
 
2742
                *id = dst = mem_heap_alloc(heap, len);
2865
2743
 
2866
2744
                innobase_convert_from_id(cs, dst, str, len);
2867
 
        } else if (!strncmp(str, srv_mysql50_table_name_prefix.c_str(),
2868
 
                            srv_mysql50_table_name_prefix.size())) {
 
2745
        } else if (!strncmp(str, srv_mysql50_table_name_prefix,
 
2746
                            sizeof srv_mysql50_table_name_prefix)) {
2869
2747
                /* This is a pre-5.1 table name
2870
2748
                containing chars other than [A-Za-z0-9].
2871
2749
                Discard the prefix and use raw UTF-8 encoding. */
2872
 
                str += srv_mysql50_table_name_prefix.size();
2873
 
                len -= srv_mysql50_table_name_prefix.size();
 
2750
                str += sizeof srv_mysql50_table_name_prefix;
 
2751
                len -= sizeof srv_mysql50_table_name_prefix;
2874
2752
                goto convert_id;
2875
2753
        } else {
2876
2754
                /* Encode using filename-safe characters. */
2877
2755
                len = 5 * len + 1;
2878
 
                *id = dst = static_cast<char *>(mem_heap_alloc(heap, len));
 
2756
                *id = dst = mem_heap_alloc(heap, len);
2879
2757
 
2880
2758
                innobase_convert_from_table_id(cs, dst, str, len);
2881
2759
        }
3013
2891
        table_name_len = strlen(table_name);
3014
2892
 
3015
2893
        /* Copy database_name, '/', table_name, '\0' */
3016
 
        ref = static_cast<char *>(mem_heap_alloc(heap, database_name_len + table_name_len + 2));
 
2894
        ref = mem_heap_alloc(heap, database_name_len + table_name_len + 2);
3017
2895
        memcpy(ref, database_name, database_name_len);
3018
2896
        ref[database_name_len] = '/';
3019
2897
        memcpy(ref + database_name_len + 1, table_name, table_name_len + 1);
3070
2948
char*
3071
2949
dict_strip_comments(
3072
2950
/*================*/
3073
 
        const char*     sql_string,     /*!< in: SQL string */
3074
 
        size_t          sql_length)     /*!< in: length of sql_string */
 
2951
        const char*     sql_string)     /*!< in: SQL string */
3075
2952
{
3076
2953
        char*           str;
3077
2954
        const char*     sptr;
3078
 
        const char*     eptr    = sql_string + sql_length;
3079
2955
        char*           ptr;
3080
2956
        /* unclosed quote character (0 if none) */
3081
2957
        char            quote   = 0;
3082
2958
 
3083
 
        str = static_cast<char *>(mem_alloc(sql_length + 1));
 
2959
        str = mem_alloc(strlen(sql_string) + 1);
3084
2960
 
3085
2961
        sptr = sql_string;
3086
2962
        ptr = str;
3087
2963
 
3088
2964
        for (;;) {
3089
2965
scan_more:
3090
 
                if (sptr >= eptr || *sptr == '\0') {
3091
 
end_of_string:
 
2966
                if (*sptr == '\0') {
3092
2967
                        *ptr = '\0';
3093
2968
 
3094
 
                        ut_a(ptr <= str + sql_length);
 
2969
                        ut_a(ptr <= str + strlen(sql_string));
3095
2970
 
3096
2971
                        return(str);
3097
2972
                }
3110
2985
                           || (sptr[0] == '-' && sptr[1] == '-'
3111
2986
                               && sptr[2] == ' ')) {
3112
2987
                        for (;;) {
3113
 
                                if (++sptr >= eptr) {
3114
 
                                        goto end_of_string;
3115
 
                                }
3116
 
 
3117
2988
                                /* In Unix a newline is 0x0A while in Windows
3118
2989
                                it is 0x0D followed by 0x0A */
3119
2990
 
3120
 
                                switch (*sptr) {
3121
 
                                case (char) 0X0A:
3122
 
                                case (char) 0x0D:
3123
 
                                case '\0':
 
2991
                                if (*sptr == (char)0x0A
 
2992
                                    || *sptr == (char)0x0D
 
2993
                                    || *sptr == '\0') {
 
2994
 
3124
2995
                                        goto scan_more;
3125
2996
                                }
 
2997
 
 
2998
                                sptr++;
3126
2999
                        }
3127
3000
                } else if (!quote && *sptr == '/' && *(sptr + 1) == '*') {
3128
 
                        sptr += 2;
3129
3001
                        for (;;) {
3130
 
                                if (sptr >= eptr) {
3131
 
                                        goto end_of_string;
 
3002
                                if (*sptr == '*' && *(sptr + 1) == '/') {
 
3003
 
 
3004
                                        sptr += 2;
 
3005
 
 
3006
                                        goto scan_more;
3132
3007
                                }
3133
3008
 
3134
 
                                switch (*sptr) {
3135
 
                                case '\0':
 
3009
                                if (*sptr == '\0') {
 
3010
 
3136
3011
                                        goto scan_more;
3137
 
                                case '*':
3138
 
                                        if (sptr[1] == '/') {
3139
 
                                                sptr += 2;
3140
 
                                                goto scan_more;
3141
 
                                        }
3142
3012
                                }
3143
3013
 
3144
3014
                                sptr++;
3485
3355
                        start_of_latest_foreign);
3486
3356
                mutex_exit(&dict_foreign_err_mutex);
3487
3357
 
3488
 
                return(DB_CHILD_NO_INDEX);
 
3358
                return(DB_CANNOT_ADD_CONSTRAINT);
3489
3359
        }
3490
3360
        ptr = dict_accept(cs, ptr, "REFERENCES", &success);
3491
3361
 
3509
3379
 
3510
3380
                db_len = dict_get_db_name_len(table->name);
3511
3381
 
3512
 
                foreign->id = static_cast<char*>(mem_heap_alloc(
3513
 
                        foreign->heap, db_len + strlen(constraint_name) + 2));
 
3382
                foreign->id = mem_heap_alloc(
 
3383
                        foreign->heap, db_len + strlen(constraint_name) + 2);
3514
3384
 
3515
3385
                ut_memcpy(foreign->id, table->name, db_len);
3516
3386
                foreign->id[db_len] = '/';
3522
3392
                                                      table->name);
3523
3393
        foreign->foreign_index = index;
3524
3394
        foreign->n_fields = (unsigned int) i;
3525
 
        foreign->foreign_col_names = static_cast<const char **>(mem_heap_alloc(foreign->heap,
3526
 
                                                    i * sizeof(void*)));
 
3395
        foreign->foreign_col_names = mem_heap_alloc(foreign->heap,
 
3396
                                                    i * sizeof(void*));
3527
3397
        for (i = 0; i < foreign->n_fields; i++) {
3528
3398
                foreign->foreign_col_names[i] = mem_heap_strdup(
3529
3399
                        foreign->heap,
3766
3636
                                start_of_latest_foreign);
3767
3637
                        mutex_exit(&dict_foreign_err_mutex);
3768
3638
 
3769
 
                        return(DB_PARENT_NO_INDEX);
 
3639
                        return(DB_CANNOT_ADD_CONSTRAINT);
3770
3640
                }
3771
3641
        } else {
3772
3642
                ut_a(trx->check_foreigns == FALSE);
3779
3649
        foreign->referenced_table_name
3780
3650
                = mem_heap_strdup(foreign->heap, referenced_table_name);
3781
3651
 
3782
 
        foreign->referenced_col_names = static_cast<const char **>(mem_heap_alloc(foreign->heap,
3783
 
                                                       i * sizeof(void*)));
 
3652
        foreign->referenced_col_names = mem_heap_alloc(foreign->heap,
 
3653
                                                       i * sizeof(void*));
3784
3654
        for (i = 0; i < foreign->n_fields; i++) {
3785
3655
                foreign->referenced_col_names[i]
3786
3656
                        = mem_heap_strdup(foreign->heap, column_names[i]);
3819
3689
                                        name before it: test.table2; the
3820
3690
                                        default database id the database of
3821
3691
                                        parameter name */
3822
 
        size_t          sql_length,     /*!< in: length of sql_string */
3823
3692
        const char*     name,           /*!< in: table full name in the
3824
3693
                                        normalized form
3825
3694
                                        database_name/table_name */
3834
3703
        ut_a(trx);
3835
3704
        ut_a(trx->mysql_thd);
3836
3705
 
3837
 
        str = dict_strip_comments(sql_string, sql_length);
 
3706
        str = dict_strip_comments(sql_string);
3838
3707
        heap = mem_heap_create(10000);
3839
3708
 
3840
3709
        err = dict_create_foreign_constraints_low(
3841
 
                trx, heap, trx->session()->charset(), str, name,
 
3710
                trx, heap, innobase_get_charset(trx->mysql_thd), str, name,
3842
3711
                reject_fks);
3843
3712
 
3844
3713
        mem_heap_free(heap);
3867
3736
        dict_foreign_t*         foreign;
3868
3737
        ibool                   success;
3869
3738
        char*                   str;
3870
 
        size_t                  len;
3871
3739
        const char*             ptr;
3872
3740
        const char*             id;
3873
3741
        FILE*                   ef      = dict_foreign_err_file;
3876
3744
        ut_a(trx);
3877
3745
        ut_a(trx->mysql_thd);
3878
3746
 
3879
 
        cs = trx->session()->charset();
 
3747
        cs = innobase_get_charset(trx->mysql_thd);
3880
3748
 
3881
3749
        *n = 0;
3882
3750
 
3883
 
        *constraints_to_drop = static_cast<const char **>(mem_heap_alloc(heap, 1000 * sizeof(char*)));
3884
 
 
3885
 
        ptr= trx->session()->getQueryStringCopy(len);
3886
 
 
3887
 
        str = dict_strip_comments(ptr, len);
3888
 
 
 
3751
        *constraints_to_drop = mem_heap_alloc(heap, 1000 * sizeof(char*));
 
3752
 
 
3753
        str = dict_strip_comments((trx->mysql_query_str));
3889
3754
        ptr = str;
3890
3755
 
3891
3756
        ut_ad(mutex_own(&(dict_sys->mutex)));
3994
3859
dict_index_t*
3995
3860
dict_index_get_if_in_cache_low(
3996
3861
/*===========================*/
3997
 
        index_id_t      index_id)       /*!< in: index id */
 
3862
        dulint  index_id)       /*!< in: index id */
3998
3863
{
3999
3864
        ut_ad(mutex_own(&(dict_sys->mutex)));
4000
3865
 
4009
3874
dict_index_t*
4010
3875
dict_index_get_if_in_cache(
4011
3876
/*=======================*/
4012
 
        index_id_t      index_id)       /*!< in: index id */
 
3877
        dulint  index_id)       /*!< in: index id */
4013
3878
{
4014
3879
        dict_index_t*   index;
4015
3880
 
4097
3962
 
4098
3963
        dict_index_copy_types(tuple, index, n_unique);
4099
3964
 
4100
 
        buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
 
3965
        buf = mem_heap_alloc(heap, 4);
4101
3966
 
4102
3967
        mach_write_to_4(buf, page_no);
4103
3968
 
4230
4095
are used in query optimization. */
4231
4096
UNIV_INTERN
4232
4097
void
4233
 
dict_update_statistics(
4234
 
/*===================*/
 
4098
dict_update_statistics_low(
 
4099
/*=======================*/
4235
4100
        dict_table_t*   table,          /*!< in/out: table */
4236
 
        ibool           only_calc_if_missing_stats)/*!< in: only
4237
 
                                        update/recalc the stats if they have
4238
 
                                        not been initialized yet, otherwise
4239
 
                                        do nothing */
 
4101
        ibool           has_dict_mutex __attribute__((unused)))
 
4102
                                        /*!< in: TRUE if the caller has the
 
4103
                                        dictionary mutex */
4240
4104
{
4241
4105
        dict_index_t*   index;
 
4106
        ulint           size;
4242
4107
        ulint           sum_of_index_sizes      = 0;
4243
4108
 
4244
4109
        if (table->ibd_file_missing) {
4253
4118
                return;
4254
4119
        }
4255
4120
 
 
4121
        /* If we have set a high innodb_force_recovery level, do not calculate
 
4122
        statistics, as a badly corrupted index can cause a crash in it. */
 
4123
 
 
4124
        if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
 
4125
 
 
4126
                return;
 
4127
        }
 
4128
 
4256
4129
        /* Find out the sizes of the indexes and how many different values
4257
4130
        for the key they approximately have */
4258
4131
 
4264
4137
                return;
4265
4138
        }
4266
4139
 
4267
 
        dict_table_stats_lock(table, RW_X_LATCH);
4268
 
 
4269
 
        if (only_calc_if_missing_stats && table->stat_initialized) {
4270
 
                dict_table_stats_unlock(table, RW_X_LATCH);
4271
 
                return;
4272
 
        }
4273
 
 
4274
 
        do {
4275
 
                if (UNIV_LIKELY
4276
 
                    (srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE
4277
 
                     || (srv_force_recovery < SRV_FORCE_NO_LOG_REDO
4278
 
                         && dict_index_is_clust(index)))) {
4279
 
                        ulint   size;
4280
 
                        size = btr_get_size(index, BTR_TOTAL_SIZE);
4281
 
 
4282
 
                        index->stat_index_size = size;
4283
 
 
4284
 
                        sum_of_index_sizes += size;
4285
 
 
4286
 
                        size = btr_get_size(index, BTR_N_LEAF_PAGES);
4287
 
 
4288
 
                        if (size == 0) {
4289
 
                                /* The root node of the tree is a leaf */
4290
 
                                size = 1;
4291
 
                        }
4292
 
 
4293
 
                        index->stat_n_leaf_pages = size;
4294
 
 
4295
 
                        btr_estimate_number_of_different_key_vals(index);
4296
 
                } else {
4297
 
                        /* If we have set a high innodb_force_recovery
4298
 
                        level, do not calculate statistics, as a badly
4299
 
                        corrupted index can cause a crash in it.
4300
 
                        Initialize some bogus index cardinality
4301
 
                        statistics, so that the data can be queried in
4302
 
                        various means, also via secondary indexes. */
4303
 
                        ulint   i;
4304
 
 
4305
 
                        sum_of_index_sizes++;
4306
 
                        index->stat_index_size = index->stat_n_leaf_pages = 1;
4307
 
 
4308
 
                        for (i = dict_index_get_n_unique(index); i; ) {
4309
 
                                index->stat_n_diff_key_vals[i--] = 1;
4310
 
                        }
 
4140
        while (index) {
 
4141
                size = btr_get_size(index, BTR_TOTAL_SIZE);
 
4142
 
 
4143
                index->stat_index_size = size;
 
4144
 
 
4145
                sum_of_index_sizes += size;
 
4146
 
 
4147
                size = btr_get_size(index, BTR_N_LEAF_PAGES);
 
4148
 
 
4149
                if (size == 0) {
 
4150
                        /* The root node of the tree is a leaf */
 
4151
                        size = 1;
4311
4152
                }
4312
4153
 
 
4154
                index->stat_n_leaf_pages = size;
 
4155
 
 
4156
                btr_estimate_number_of_different_key_vals(index);
 
4157
 
4313
4158
                index = dict_table_get_next_index(index);
4314
 
        } while (index);
 
4159
        }
4315
4160
 
4316
4161
        index = dict_table_get_first_index(table);
4317
4162
 
4326
4171
        table->stat_initialized = TRUE;
4327
4172
 
4328
4173
        table->stat_modified_counter = 0;
 
4174
}
4329
4175
 
4330
 
        dict_table_stats_unlock(table, RW_X_LATCH);
 
4176
/*********************************************************************//**
 
4177
Calculates new estimates for table and index statistics. The statistics
 
4178
are used in query optimization. */
 
4179
UNIV_INTERN
 
4180
void
 
4181
dict_update_statistics(
 
4182
/*===================*/
 
4183
        dict_table_t*   table)  /*!< in/out: table */
 
4184
{
 
4185
        dict_update_statistics_low(table, FALSE);
4331
4186
}
4332
4187
 
4333
4188
/**********************************************************************//**
4407
4262
 
4408
4263
        ut_ad(mutex_own(&(dict_sys->mutex)));
4409
4264
 
4410
 
        dict_update_statistics(table, FALSE /* update even if initialized */);
4411
 
 
4412
 
        dict_table_stats_lock(table, RW_S_LATCH);
 
4265
        dict_update_statistics_low(table, TRUE);
4413
4266
 
4414
4267
        fprintf(stderr,
4415
4268
                "--------------------------------------\n"
4416
 
                "TABLE: name %s, id %llu, flags %lx, columns %lu,"
 
4269
                "TABLE: name %s, id %lu %lu, flags %lx, columns %lu,"
4417
4270
                " indexes %lu, appr.rows %lu\n"
4418
4271
                "  COLUMNS: ",
4419
4272
                table->name,
4420
 
                (ullint) table->id,
 
4273
                (ulong) ut_dulint_get_high(table->id),
 
4274
                (ulong) ut_dulint_get_low(table->id),
4421
4275
                (ulong) table->flags,
4422
4276
                (ulong) table->n_cols,
4423
4277
                (ulong) UT_LIST_GET_LEN(table->indexes),
4437
4291
                index = UT_LIST_GET_NEXT(indexes, index);
4438
4292
        }
4439
4293
 
4440
 
        dict_table_stats_unlock(table, RW_S_LATCH);
4441
 
 
4442
4294
        foreign = UT_LIST_GET_FIRST(table->foreign_list);
4443
4295
 
4444
4296
        while (foreign != NULL) {
4484
4336
{
4485
4337
        ib_int64_t      n_vals;
4486
4338
        ulint           i;
 
4339
        const char*     type_string;
4487
4340
 
4488
4341
        ut_ad(mutex_own(&(dict_sys->mutex)));
4489
4342
 
4494
4347
                n_vals = index->stat_n_diff_key_vals[1];
4495
4348
        }
4496
4349
 
 
4350
        if (dict_index_is_clust(index)) {
 
4351
                type_string = "clustered index";
 
4352
        } else if (dict_index_is_unique(index)) {
 
4353
                type_string = "unique index";
 
4354
        } else {
 
4355
                type_string = "secondary index";
 
4356
        }
 
4357
 
4497
4358
        fprintf(stderr,
4498
 
                "  INDEX: name %s, id %llu, fields %lu/%lu,"
 
4359
                "  INDEX: name %s, id %lu %lu, fields %lu/%lu,"
4499
4360
                " uniq %lu, type %lu\n"
4500
4361
                "   root page %lu, appr.key vals %lu,"
4501
4362
                " leaf pages %lu, size pages %lu\n"
4502
4363
                "   FIELDS: ",
4503
4364
                index->name,
4504
 
                (ullint) index->id,
 
4365
                (ulong) ut_dulint_get_high(index->id),
 
4366
                (ulong) ut_dulint_get_low(index->id),
4505
4367
                (ulong) index->n_user_defined_cols,
4506
4368
                (ulong) index->n_fields,
4507
4369
                (ulong) index->n_uniq,
4530
4392
void
4531
4393
dict_field_print_low(
4532
4394
/*=================*/
4533
 
        const dict_field_t*     field)  /*!< in: field */
 
4395
        dict_field_t*   field)  /*!< in: field */
4534
4396
{
4535
4397
        ut_ad(mutex_own(&(dict_sys->mutex)));
4536
4398
 
4780
4642
        dict_ind_redundant->cached = dict_ind_compact->cached = TRUE;
4781
4643
}
4782
4644
 
4783
 
/**********************************************************************//**
4784
 
Frees dict_ind_redundant and dict_ind_compact. */
4785
 
static
4786
 
void
4787
 
dict_ind_free(void)
4788
 
/*===============*/
4789
 
{
4790
 
        dict_table_t*   table;
4791
 
 
4792
 
        table = dict_ind_compact->table;
4793
 
        dict_mem_index_free(dict_ind_compact);
4794
 
        dict_ind_compact = NULL;
4795
 
        dict_mem_table_free(table);
4796
 
 
4797
 
        table = dict_ind_redundant->table;
4798
 
        dict_mem_index_free(dict_ind_redundant);
4799
 
        dict_ind_redundant = NULL;
4800
 
        dict_mem_table_free(table);
4801
 
}
4802
 
 
4803
4645
#ifndef UNIV_HOTBACKUP
4804
4646
/**********************************************************************//**
4805
4647
Get index by name
4836
4678
dict_table_replace_index_in_foreign_list(
4837
4679
/*=====================================*/
4838
4680
        dict_table_t*   table,  /*!< in/out: table */
4839
 
        dict_index_t*   index,  /*!< in: index to be replaced */
4840
 
        const trx_t*    trx)    /*!< in: transaction handle */
 
4681
        dict_index_t*   index)  /*!< in: index to be replaced */
4841
4682
{
4842
4683
        dict_foreign_t* foreign;
4843
4684
 
4848
4689
                if (foreign->foreign_index == index) {
4849
4690
                        dict_index_t*   new_index
4850
4691
                                = dict_foreign_find_equiv_index(foreign);
4851
 
 
4852
 
                        /* There must exist an alternative index if
4853
 
                        check_foreigns (FOREIGN_KEY_CHECKS) is on, 
4854
 
                        since ha_innobase::prepare_drop_index had done
4855
 
                        the check before we reach here. */
4856
 
 
4857
 
                        ut_a(new_index || !trx->check_foreigns);
 
4692
                        ut_a(new_index);
4858
4693
 
4859
4694
                        foreign->foreign_index = new_index;
4860
4695
                }
4880
4715
 
4881
4716
        while (index != NULL) {
4882
4717
                if (ut_strcmp(index->name, name) == 0) {
4883
 
                        if (!min_index || index->id < min_index->id) {
 
4718
                        if (!min_index
 
4719
                            || ut_dulint_cmp(index->id, min_index->id) < 0) {
4884
4720
 
4885
4721
                                min_index = index;
4886
4722
                        }
4900
4736
void
4901
4737
dict_table_check_for_dup_indexes(
4902
4738
/*=============================*/
4903
 
        const dict_table_t*     table,  /*!< in: Check for dup indexes
 
4739
        const dict_table_t*     table)  /*!< in: Check for dup indexes
4904
4740
                                        in this table */
4905
 
        ibool                   tmp_ok) /*!< in: TRUE=allow temporary
4906
 
                                        index names */
4907
4741
{
4908
4742
        /* Check for duplicates, ignoring indexes that are marked
4909
4743
        as to be dropped */
4911
4745
        const dict_index_t*     index1;
4912
4746
        const dict_index_t*     index2;
4913
4747
 
4914
 
        ut_ad(mutex_own(&dict_sys->mutex));
4915
 
 
4916
4748
        /* The primary index _must_ exist */
4917
4749
        ut_a(UT_LIST_GET_LEN(table->indexes) > 0);
4918
4750
 
4919
4751
        index1 = UT_LIST_GET_FIRST(table->indexes);
4920
 
 
4921
 
        do {
4922
 
                ut_ad(tmp_ok || *index1->name != TEMP_INDEX_PREFIX);
4923
 
 
4924
 
                index2 = UT_LIST_GET_NEXT(indexes, index1);
 
4752
        index2 = UT_LIST_GET_NEXT(indexes, index1);
 
4753
 
 
4754
        while (index1 && index2) {
4925
4755
 
4926
4756
                while (index2) {
4927
4757
 
4933
4763
                }
4934
4764
 
4935
4765
                index1 = UT_LIST_GET_NEXT(indexes, index1);
4936
 
        } while (index1);
 
4766
                index2 = UT_LIST_GET_NEXT(indexes, index1);
 
4767
        }
4937
4768
}
4938
4769
#endif /* UNIV_DEBUG */
4939
 
 
4940
 
/**************************************************************************
4941
 
Closes the data dictionary module. */
4942
 
UNIV_INTERN
4943
 
void
4944
 
dict_close(void)
4945
 
/*============*/
4946
 
{
4947
 
        ulint   i;
4948
 
 
4949
 
        /* Free the hash elements. We don't remove them from the table
4950
 
        because we are going to destroy the table anyway. */
4951
 
        for (i = 0; i < hash_get_n_cells(dict_sys->table_hash); i++) {
4952
 
                dict_table_t*   table;
4953
 
 
4954
 
                table = static_cast<dict_table_t *>(HASH_GET_FIRST(dict_sys->table_hash, i));
4955
 
 
4956
 
                while (table) {
4957
 
                        dict_table_t*   prev_table = table;
4958
 
 
4959
 
                        table = static_cast<dict_table_t *>(HASH_GET_NEXT(name_hash, prev_table));
4960
 
#ifdef UNIV_DEBUG
4961
 
                        ut_a(prev_table->magic_n == DICT_TABLE_MAGIC_N);
4962
 
#endif
4963
 
                        /* Acquire only because it's a pre-condition. */
4964
 
                        mutex_enter(&dict_sys->mutex);
4965
 
 
4966
 
                        dict_table_remove_from_cache(prev_table);
4967
 
 
4968
 
                        mutex_exit(&dict_sys->mutex);
4969
 
                }
4970
 
        }
4971
 
 
4972
 
        hash_table_free(dict_sys->table_hash);
4973
 
 
4974
 
        /* The elements are the same instance as in dict_sys->table_hash,
4975
 
        therefore we don't delete the individual elements. */
4976
 
        hash_table_free(dict_sys->table_id_hash);
4977
 
 
4978
 
        dict_ind_free();
4979
 
 
4980
 
        mutex_free(&dict_sys->mutex);
4981
 
 
4982
 
        rw_lock_free(&dict_operation_lock);
4983
 
        memset(&dict_operation_lock, 0x0, sizeof(dict_operation_lock));
4984
 
 
4985
 
        mutex_free(&dict_foreign_err_mutex);
4986
 
 
4987
 
        mem_free(dict_sys);
4988
 
        dict_sys = NULL;
4989
 
 
4990
 
        for (i = 0; i < DICT_TABLE_STATS_LATCHES_SIZE; i++) {
4991
 
                rw_lock_free(&dict_table_stats_latches[i]);
4992
 
        }
4993
 
}
4994
4770
#endif /* !UNIV_HOTBACKUP */