~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2010-07-20 02:17:09 UTC
  • mto: This revision was merged to the branch mainline in revision 1665.
  • Revision ID: brian@gaz-20100720021709-1yeehbw8d5vbtmlc
Removed identifier bit

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
 
69
69
on the mode in trx_struct::dict_operation_lock_mode */
70
70
UNIV_INTERN rw_lock_t   dict_operation_lock;
71
71
 
72
 
/* Keys to register rwlocks and mutexes with performance schema */
73
 
#ifdef UNIV_PFS_RWLOCK
74
 
UNIV_INTERN mysql_pfs_key_t     dict_operation_lock_key;
75
 
UNIV_INTERN mysql_pfs_key_t     index_tree_rw_lock_key;
76
 
#endif /* UNIV_PFS_RWLOCK */
77
 
 
78
 
#ifdef UNIV_PFS_MUTEX
79
 
UNIV_INTERN mysql_pfs_key_t     dict_sys_mutex_key;
80
 
UNIV_INTERN mysql_pfs_key_t     dict_foreign_err_mutex_key;
81
 
#endif /* UNIV_PFS_MUTEX */
82
 
 
83
72
#define DICT_HEAP_SIZE          100     /*!< initial memory heap size when
84
73
                                        creating a table or index object */
85
74
#define DICT_POOL_PER_TABLE_HASH 512    /*!< buffer pool max size per table
90
79
/** Identifies generated InnoDB foreign key names */
91
80
static char     dict_ibfk[] = "_ibfk_";
92
81
 
93
 
/** array of mutexes protecting dict_index_t::stat_n_diff_key_vals[] */
94
 
#define DICT_INDEX_STAT_MUTEX_SIZE      32
95
 
static mutex_t  dict_index_stat_mutex[DICT_INDEX_STAT_MUTEX_SIZE];
96
 
 
97
82
/*******************************************************************//**
98
83
Tries to find column names for the index and sets the col field of the
99
 
index.
100
 
@return TRUE if the column names were found */
 
84
index. */
101
85
static
102
 
ibool
 
86
void
103
87
dict_index_find_cols(
104
88
/*=================*/
105
89
        dict_table_t*   table,  /*!< in: table */
154
138
void
155
139
dict_field_print_low(
156
140
/*=================*/
157
 
        const dict_field_t*     field); /*!< in: field */
 
141
        dict_field_t*   field); /*!< in: field */
158
142
/*********************************************************************//**
159
143
Frees a foreign key struct. */
160
144
static
253
237
        mutex_exit(&(dict_sys->mutex));
254
238
}
255
239
 
256
 
/** Get the mutex that protects index->stat_n_diff_key_vals[] */
257
 
#define GET_INDEX_STAT_MUTEX(index) \
258
 
        (&dict_index_stat_mutex[ut_fold_ull(index->id) \
259
 
                                % DICT_INDEX_STAT_MUTEX_SIZE])
260
 
 
261
 
/**********************************************************************//**
262
 
Lock the appropriate mutex to protect index->stat_n_diff_key_vals[].
263
 
index->id is used to pick the right mutex and it should not change
264
 
before dict_index_stat_mutex_exit() is called on this index. */
265
 
UNIV_INTERN
266
 
void
267
 
dict_index_stat_mutex_enter(
268
 
/*========================*/
269
 
        const dict_index_t*     index)  /*!< in: index */
270
 
{
271
 
        ut_ad(index != NULL);
272
 
        ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
273
 
        ut_ad(index->cached);
274
 
        ut_ad(!index->to_be_dropped);
275
 
 
276
 
        mutex_enter(GET_INDEX_STAT_MUTEX(index));
277
 
}
278
 
 
279
 
/**********************************************************************//**
280
 
Unlock the appropriate mutex that protects index->stat_n_diff_key_vals[]. */
281
 
UNIV_INTERN
282
 
void
283
 
dict_index_stat_mutex_exit(
284
 
/*=======================*/
285
 
        const dict_index_t*     index)  /*!< in: index */
286
 
{
287
 
        ut_ad(index != NULL);
288
 
        ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
289
 
        ut_ad(index->cached);
290
 
        ut_ad(!index->to_be_dropped);
291
 
 
292
 
        mutex_exit(GET_INDEX_STAT_MUTEX(index));
293
 
}
294
 
 
295
240
/********************************************************************//**
296
241
Decrements the count of open MySQL handles to a table. */
297
242
UNIV_INTERN
424
369
dict_index_get_on_id_low(
425
370
/*=====================*/
426
371
        dict_table_t*   table,  /*!< in: table */
427
 
        index_id_t      id)     /*!< in: index id */
 
372
        dulint          id)     /*!< in: index id */
428
373
{
429
374
        dict_index_t*   index;
430
375
 
431
376
        index = dict_table_get_first_index(table);
432
377
 
433
378
        while (index) {
434
 
                if (id == index->id) {
 
379
                if (0 == ut_dulint_cmp(id, index->id)) {
435
380
                        /* Found */
436
381
 
437
382
                        return(index);
573
518
dict_table_t*
574
519
dict_table_get_on_id(
575
520
/*=================*/
576
 
        table_id_t      table_id,       /*!< in: table id */
577
 
        trx_t*          trx)            /*!< in: transaction handle */
 
521
        dulint  table_id,       /*!< in: table id */
 
522
        trx_t*  trx)            /*!< in: transaction handle */
578
523
{
579
524
        dict_table_t*   table;
580
525
 
581
 
        if (trx->dict_operation_lock_mode == RW_X_LATCH) {
582
 
 
583
 
                /* Note: An X latch implies that the transaction
584
 
                already owns the dictionary mutex. */
585
 
 
586
 
                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);
587
535
 
588
536
                return(dict_table_get_on_id_low(table_id));
589
537
        }
655
603
dict_init(void)
656
604
/*===========*/
657
605
{
658
 
        int     i;
659
 
 
660
606
        dict_sys = mem_alloc(sizeof(dict_sys_t));
661
607
 
662
 
        mutex_create(dict_sys_mutex_key, &dict_sys->mutex, SYNC_DICT);
 
608
        mutex_create(&dict_sys->mutex, SYNC_DICT);
663
609
 
664
610
        dict_sys->table_hash = hash_create(buf_pool_get_curr_size()
665
611
                                           / (DICT_POOL_PER_TABLE_HASH
671
617
 
672
618
        UT_LIST_INIT(dict_sys->table_LRU);
673
619
 
674
 
        rw_lock_create(dict_operation_lock_key,
675
 
                       &dict_operation_lock, SYNC_DICT_OPERATION);
 
620
        rw_lock_create(&dict_operation_lock, SYNC_DICT_OPERATION);
676
621
 
677
622
        dict_foreign_err_file = os_file_create_tmpfile();
678
623
        ut_a(dict_foreign_err_file);
679
624
 
680
 
        mutex_create(dict_foreign_err_mutex_key,
681
 
                     &dict_foreign_err_mutex, SYNC_ANY_LATCH);
682
 
 
683
 
        for (i = 0; i < DICT_INDEX_STAT_MUTEX_SIZE; i++) {
684
 
          mutex_create(PFS_NOT_INSTRUMENTED,
685
 
                       &dict_index_stat_mutex[i], SYNC_INDEX_TREE);
686
 
        }
 
625
        mutex_create(&dict_foreign_err_mutex, SYNC_ANY_LATCH);
687
626
}
688
627
 
689
628
/**********************************************************************//**
796
735
        table->cached = TRUE;
797
736
 
798
737
        fold = ut_fold_string(table->name);
799
 
        id_fold = ut_fold_ull(table->id);
 
738
        id_fold = ut_fold_dulint(table->id);
800
739
 
801
740
        row_len = 0;
802
741
        for (i = 0; i < table->n_def; i++) {
838
777
                dict_table_t*   table2;
839
778
                HASH_SEARCH(id_hash, dict_sys->table_id_hash, id_fold,
840
779
                            dict_table_t*, table2, ut_ad(table2->cached),
841
 
                            table2->id == table->id);
 
780
                            ut_dulint_cmp(table2->id, table->id) == 0);
842
781
                ut_a(table2 == NULL);
843
782
 
844
783
#ifdef UNIV_DEBUG
860
799
        /* Add table to LRU list of tables */
861
800
        UT_LIST_ADD_FIRST(table_LRU, dict_sys->table_LRU, table);
862
801
 
863
 
        dict_sys->size += mem_heap_get_size(table->heap)
864
 
                + strlen(table->name) + 1;
 
802
        dict_sys->size += mem_heap_get_size(table->heap);
865
803
}
866
804
 
867
805
/**********************************************************************//**
873
811
dict_index_t*
874
812
dict_index_find_on_id_low(
875
813
/*======================*/
876
 
        index_id_t      id)     /*!< in: index id */
 
814
        dulint  id)     /*!< in: index id */
877
815
{
878
816
        dict_table_t*   table;
879
817
        dict_index_t*   index;
884
822
                index = dict_table_get_first_index(table);
885
823
 
886
824
                while (index) {
887
 
                        if (id == index->id) {
 
825
                        if (0 == ut_dulint_cmp(id, index->id)) {
888
826
                                /* Found */
889
827
 
890
828
                                return(index);
915
853
        dict_foreign_t* foreign;
916
854
        dict_index_t*   index;
917
855
        ulint           fold;
918
 
        char            old_name[MAX_TABLE_NAME_LEN + 1];
 
856
        ulint           old_size;
 
857
        const char*     old_name;
919
858
 
920
859
        ut_ad(table);
921
860
        ut_ad(mutex_own(&(dict_sys->mutex)));
922
861
 
923
 
        /* store the old/current name to an automatic variable */
924
 
        if (strlen(table->name) + 1 <= sizeof(old_name)) {
925
 
                memcpy(old_name, table->name, strlen(table->name) + 1);
926
 
        } else {
927
 
                ut_print_timestamp(stderr);
928
 
                fprintf(stderr, "InnoDB: too long table name: '%s', "
929
 
                        "max length is %d\n", table->name,
930
 
                        MAX_TABLE_NAME_LEN);
931
 
                ut_error;
932
 
        }
 
862
        old_size = mem_heap_get_size(table->heap);
 
863
        old_name = table->name;
933
864
 
934
865
        fold = ut_fold_string(new_name);
935
866
 
975
906
        /* Remove table from the hash tables of tables */
976
907
        HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash,
977
908
                    ut_fold_string(old_name), table);
978
 
 
979
 
        if (strlen(new_name) > strlen(table->name)) {
980
 
                /* We allocate MAX_TABLE_NAME_LEN+1 bytes here to avoid
981
 
                memory fragmentation, we assume a repeated calls of
982
 
                ut_realloc() with the same size do not cause fragmentation */
983
 
                ut_a(strlen(new_name) <= MAX_TABLE_NAME_LEN);
984
 
                table->name = ut_realloc(table->name, MAX_TABLE_NAME_LEN + 1);
985
 
        }
986
 
        memcpy(table->name, new_name, strlen(new_name) + 1);
 
909
        table->name = mem_heap_strdup(table->heap, new_name);
987
910
 
988
911
        /* Add table to hash table of tables */
989
912
        HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold,
990
913
                    table);
991
 
 
992
 
        dict_sys->size += strlen(new_name) - strlen(old_name);
993
 
        ut_a(dict_sys->size > 0);
 
914
        dict_sys->size += (mem_heap_get_size(table->heap) - old_size);
994
915
 
995
916
        /* Update the table_name field in indexes */
996
917
        index = dict_table_get_first_index(table);
1140
1061
dict_table_change_id_in_cache(
1141
1062
/*==========================*/
1142
1063
        dict_table_t*   table,  /*!< in/out: table object already in cache */
1143
 
        table_id_t      new_id) /*!< in: new id to set */
 
1064
        dulint          new_id) /*!< in: new id to set */
1144
1065
{
1145
1066
        ut_ad(table);
1146
1067
        ut_ad(mutex_own(&(dict_sys->mutex)));
1149
1070
        /* Remove the table from the hash table of id's */
1150
1071
 
1151
1072
        HASH_DELETE(dict_table_t, id_hash, dict_sys->table_id_hash,
1152
 
                    ut_fold_ull(table->id), table);
 
1073
                    ut_fold_dulint(table->id), table);
1153
1074
        table->id = new_id;
1154
1075
 
1155
1076
        /* Add the table back to the hash table */
1156
1077
        HASH_INSERT(dict_table_t, id_hash, dict_sys->table_id_hash,
1157
 
                    ut_fold_ull(table->id), table);
 
1078
                    ut_fold_dulint(table->id), table);
1158
1079
}
1159
1080
 
1160
1081
/**********************************************************************//**
1210
1131
        HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash,
1211
1132
                    ut_fold_string(table->name), table);
1212
1133
        HASH_DELETE(dict_table_t, id_hash, dict_sys->table_id_hash,
1213
 
                    ut_fold_ull(table->id), table);
 
1134
                    ut_fold_dulint(table->id), table);
1214
1135
 
1215
1136
        /* Remove table from LRU list of tables */
1216
1137
        UT_LIST_REMOVE(table_LRU, dict_sys->table_LRU, table);
1217
1138
 
1218
 
        size = mem_heap_get_size(table->heap) + strlen(table->name) + 1;
 
1139
        size = mem_heap_get_size(table->heap);
1219
1140
 
1220
1141
        ut_ad(dict_sys->size >= size);
1221
1142
 
1247
1168
        ulint                   i;
1248
1169
 
1249
1170
        for (i = 0; i < UT_ARR_SIZE(reserved_names); i++) {
1250
 
                if (innobase_strcasecmp(name, reserved_names[i]) == 0) {
 
1171
                if (strcmp(name, reserved_names[i]) == 0) {
1251
1172
 
1252
1173
                        return(TRUE);
1253
1174
                }
1277
1198
                = TRX_UNDO_PAGE_HDR - TRX_UNDO_PAGE_HDR_SIZE
1278
1199
                + 2 /* next record pointer */
1279
1200
                + 1 /* type_cmpl */
1280
 
                + 11 /* trx->undo_no */ + 11 /* table->id */
 
1201
                + 11 /* trx->undo_no */ - 11 /* table->id */
1281
1202
                + 1 /* rec_get_info_bits() */
1282
1203
                + 11 /* DB_TRX_ID */
1283
1204
                + 11 /* DB_ROLL_PTR */
1509
1430
 
1510
1431
/**********************************************************************//**
1511
1432
Adds an index to the dictionary cache.
1512
 
@return DB_SUCCESS, DB_TOO_BIG_RECORD, or DB_CORRUPTION */
 
1433
@return DB_SUCCESS or DB_TOO_BIG_RECORD */
1513
1434
UNIV_INTERN
1514
1435
ulint
1515
1436
dict_index_add_to_cache(
1535
1456
        ut_a(!dict_index_is_clust(index)
1536
1457
             || UT_LIST_GET_LEN(table->indexes) == 0);
1537
1458
 
1538
 
        if (!dict_index_find_cols(table, index)) {
1539
 
 
1540
 
                dict_mem_index_free(index);
1541
 
                return(DB_CORRUPTION);
1542
 
        }
 
1459
        dict_index_find_cols(table, index);
1543
1460
 
1544
1461
        /* Build the cache internal representation of the index,
1545
1462
        containing also the added system fields */
1644
1561
        new_index->stat_n_leaf_pages = 1;
1645
1562
 
1646
1563
        new_index->page = page_no;
1647
 
        rw_lock_create(index_tree_rw_lock_key, &new_index->lock,
1648
 
                       SYNC_INDEX_TREE);
 
1564
        rw_lock_create(&new_index->lock, SYNC_INDEX_TREE);
1649
1565
 
1650
1566
        if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) {
1651
1567
 
1748
1664
 
1749
1665
/*******************************************************************//**
1750
1666
Tries to find column names for the index and sets the col field of the
1751
 
index.
1752
 
@return TRUE if the column names were found */
 
1667
index. */
1753
1668
static
1754
 
ibool
 
1669
void
1755
1670
dict_index_find_cols(
1756
1671
/*=================*/
1757
1672
        dict_table_t*   table,  /*!< in: table */
1776
1691
                        }
1777
1692
                }
1778
1693
 
1779
 
#ifdef UNIV_DEBUG
1780
1694
                /* It is an error not to find a matching column. */
1781
1695
                fputs("InnoDB: Error: no matching column for ", stderr);
1782
1696
                ut_print_name(stderr, NULL, FALSE, field->name);
1783
1697
                fputs(" in ", stderr);
1784
1698
                dict_index_name_print(stderr, NULL, index);
1785
1699
                fputs("!\n", stderr);
1786
 
#endif /* UNIV_DEBUG */
1787
 
                return(FALSE);
 
1700
                ut_error;
1788
1701
 
1789
1702
found:
1790
1703
                ;
1791
1704
        }
1792
 
 
1793
 
        return(TRUE);
1794
1705
}
1795
1706
#endif /* !UNIV_HOTBACKUP */
1796
1707
 
2472
2383
                                /* We found a matching index, select
2473
2384
                                the index with the higher id*/
2474
2385
 
2475
 
                                if (!found || index->id > found->id) {
 
2386
                                if (!found
 
2387
                                    || ut_dulint_cmp(index->id, found->id) > 0) {
2476
2388
 
2477
2389
                                        found = index;
2478
2390
                                }
3036
2948
char*
3037
2949
dict_strip_comments(
3038
2950
/*================*/
3039
 
        const char*     sql_string,     /*!< in: SQL string */
3040
 
        size_t          sql_length)     /*!< in: length of sql_string */
 
2951
        const char*     sql_string)     /*!< in: SQL string */
3041
2952
{
3042
2953
        char*           str;
3043
2954
        const char*     sptr;
3044
 
        const char*     eptr    = sql_string + sql_length;
3045
2955
        char*           ptr;
3046
2956
        /* unclosed quote character (0 if none) */
3047
2957
        char            quote   = 0;
3048
2958
 
3049
 
        str = mem_alloc(sql_length + 1);
 
2959
        str = mem_alloc(strlen(sql_string) + 1);
3050
2960
 
3051
2961
        sptr = sql_string;
3052
2962
        ptr = str;
3053
2963
 
3054
2964
        for (;;) {
3055
2965
scan_more:
3056
 
                if (sptr >= eptr || *sptr == '\0') {
3057
 
end_of_string:
 
2966
                if (*sptr == '\0') {
3058
2967
                        *ptr = '\0';
3059
2968
 
3060
 
                        ut_a(ptr <= str + sql_length);
 
2969
                        ut_a(ptr <= str + strlen(sql_string));
3061
2970
 
3062
2971
                        return(str);
3063
2972
                }
3076
2985
                           || (sptr[0] == '-' && sptr[1] == '-'
3077
2986
                               && sptr[2] == ' ')) {
3078
2987
                        for (;;) {
3079
 
                                if (++sptr >= eptr) {
3080
 
                                        goto end_of_string;
3081
 
                                }
3082
 
 
3083
2988
                                /* In Unix a newline is 0x0A while in Windows
3084
2989
                                it is 0x0D followed by 0x0A */
3085
2990
 
3086
 
                                switch (*sptr) {
3087
 
                                case (char) 0X0A:
3088
 
                                case (char) 0x0D:
3089
 
                                case '\0':
 
2991
                                if (*sptr == (char)0x0A
 
2992
                                    || *sptr == (char)0x0D
 
2993
                                    || *sptr == '\0') {
 
2994
 
3090
2995
                                        goto scan_more;
3091
2996
                                }
 
2997
 
 
2998
                                sptr++;
3092
2999
                        }
3093
3000
                } else if (!quote && *sptr == '/' && *(sptr + 1) == '*') {
3094
 
                        sptr += 2;
3095
3001
                        for (;;) {
3096
 
                                if (sptr >= eptr) {
3097
 
                                        goto end_of_string;
 
3002
                                if (*sptr == '*' && *(sptr + 1) == '/') {
 
3003
 
 
3004
                                        sptr += 2;
 
3005
 
 
3006
                                        goto scan_more;
3098
3007
                                }
3099
3008
 
3100
 
                                switch (*sptr) {
3101
 
                                case '\0':
 
3009
                                if (*sptr == '\0') {
 
3010
 
3102
3011
                                        goto scan_more;
3103
 
                                case '*':
3104
 
                                        if (sptr[1] == '/') {
3105
 
                                                sptr += 2;
3106
 
                                                goto scan_more;
3107
 
                                        }
3108
3012
                                }
3109
3013
 
3110
3014
                                sptr++;
3785
3689
                                        name before it: test.table2; the
3786
3690
                                        default database id the database of
3787
3691
                                        parameter name */
3788
 
        size_t          sql_length,     /*!< in: length of sql_string */
3789
3692
        const char*     name,           /*!< in: table full name in the
3790
3693
                                        normalized form
3791
3694
                                        database_name/table_name */
3800
3703
        ut_a(trx);
3801
3704
        ut_a(trx->mysql_thd);
3802
3705
 
3803
 
        str = dict_strip_comments(sql_string, sql_length);
 
3706
        str = dict_strip_comments(sql_string);
3804
3707
        heap = mem_heap_create(10000);
3805
3708
 
3806
3709
        err = dict_create_foreign_constraints_low(
3833
3736
        dict_foreign_t*         foreign;
3834
3737
        ibool                   success;
3835
3738
        char*                   str;
3836
 
        size_t                  len;
3837
3739
        const char*             ptr;
3838
3740
        const char*             id;
3839
3741
        FILE*                   ef      = dict_foreign_err_file;
3848
3750
 
3849
3751
        *constraints_to_drop = mem_heap_alloc(heap, 1000 * sizeof(char*));
3850
3752
 
3851
 
        ptr = innobase_get_stmt(trx->mysql_thd, &len);
3852
 
 
3853
 
        str = dict_strip_comments(ptr, len);
3854
 
 
 
3753
        str = dict_strip_comments((trx->mysql_query_str));
3855
3754
        ptr = str;
3856
3755
 
3857
3756
        ut_ad(mutex_own(&(dict_sys->mutex)));
3960
3859
dict_index_t*
3961
3860
dict_index_get_if_in_cache_low(
3962
3861
/*===========================*/
3963
 
        index_id_t      index_id)       /*!< in: index id */
 
3862
        dulint  index_id)       /*!< in: index id */
3964
3863
{
3965
3864
        ut_ad(mutex_own(&(dict_sys->mutex)));
3966
3865
 
3975
3874
dict_index_t*
3976
3875
dict_index_get_if_in_cache(
3977
3876
/*=======================*/
3978
 
        index_id_t      index_id)       /*!< in: index id */
 
3877
        dulint  index_id)       /*!< in: index id */
3979
3878
{
3980
3879
        dict_index_t*   index;
3981
3880
 
4204
4103
                                        dictionary mutex */
4205
4104
{
4206
4105
        dict_index_t*   index;
 
4106
        ulint           size;
4207
4107
        ulint           sum_of_index_sizes      = 0;
4208
4108
 
4209
4109
        if (table->ibd_file_missing) {
4218
4118
                return;
4219
4119
        }
4220
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
 
4221
4129
        /* Find out the sizes of the indexes and how many different values
4222
4130
        for the key they approximately have */
4223
4131
 
4229
4137
                return;
4230
4138
        }
4231
4139
 
4232
 
 
4233
 
        do {
4234
 
                if (UNIV_LIKELY
4235
 
                    (srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE
4236
 
                     || (srv_force_recovery < SRV_FORCE_NO_LOG_REDO
4237
 
                         && dict_index_is_clust(index)))) {
4238
 
                        ulint   size;
4239
 
                        size = btr_get_size(index, BTR_TOTAL_SIZE);
4240
 
 
4241
 
                        index->stat_index_size = size;
4242
 
 
4243
 
                        sum_of_index_sizes += size;
4244
 
 
4245
 
                        size = btr_get_size(index, BTR_N_LEAF_PAGES);
4246
 
 
4247
 
                        if (size == 0) {
4248
 
                                /* The root node of the tree is a leaf */
4249
 
                                size = 1;
4250
 
                        }
4251
 
 
4252
 
                        index->stat_n_leaf_pages = size;
4253
 
 
4254
 
                        btr_estimate_number_of_different_key_vals(index);
4255
 
                } else {
4256
 
                        /* If we have set a high innodb_force_recovery
4257
 
                        level, do not calculate statistics, as a badly
4258
 
                        corrupted index can cause a crash in it.
4259
 
                        Initialize some bogus index cardinality
4260
 
                        statistics, so that the data can be queried in
4261
 
                        various means, also via secondary indexes. */
4262
 
                        ulint   i;
4263
 
 
4264
 
                        sum_of_index_sizes++;
4265
 
                        index->stat_index_size = index->stat_n_leaf_pages = 1;
4266
 
 
4267
 
                        for (i = dict_index_get_n_unique(index); i; ) {
4268
 
                                index->stat_n_diff_key_vals[i--] = 1;
4269
 
                        }
 
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;
4270
4152
                }
4271
4153
 
 
4154
                index->stat_n_leaf_pages = size;
 
4155
 
 
4156
                btr_estimate_number_of_different_key_vals(index);
 
4157
 
4272
4158
                index = dict_table_get_next_index(index);
4273
 
        } while (index);
 
4159
        }
4274
4160
 
4275
4161
        index = dict_table_get_first_index(table);
4276
4162
 
4277
 
        dict_index_stat_mutex_enter(index);
4278
 
 
4279
4163
        table->stat_n_rows = index->stat_n_diff_key_vals[
4280
4164
                dict_index_get_n_unique(index)];
4281
4165
 
4282
 
        dict_index_stat_mutex_exit(index);
4283
 
 
4284
4166
        table->stat_clustered_index_size = index->stat_index_size;
4285
4167
 
4286
4168
        table->stat_sum_of_other_index_sizes = sum_of_index_sizes
4384
4266
 
4385
4267
        fprintf(stderr,
4386
4268
                "--------------------------------------\n"
4387
 
                "TABLE: name %s, id %llu, flags %lx, columns %lu,"
 
4269
                "TABLE: name %s, id %lu %lu, flags %lx, columns %lu,"
4388
4270
                " indexes %lu, appr.rows %lu\n"
4389
4271
                "  COLUMNS: ",
4390
4272
                table->name,
4391
 
                (ullint) table->id,
 
4273
                (ulong) ut_dulint_get_high(table->id),
 
4274
                (ulong) ut_dulint_get_low(table->id),
4392
4275
                (ulong) table->flags,
4393
4276
                (ulong) table->n_cols,
4394
4277
                (ulong) UT_LIST_GET_LEN(table->indexes),
4453
4336
{
4454
4337
        ib_int64_t      n_vals;
4455
4338
        ulint           i;
 
4339
        const char*     type_string;
4456
4340
 
4457
4341
        ut_ad(mutex_own(&(dict_sys->mutex)));
4458
4342
 
4459
 
        dict_index_stat_mutex_enter(index);
4460
 
 
4461
4343
        if (index->n_user_defined_cols > 0) {
4462
4344
                n_vals = index->stat_n_diff_key_vals[
4463
4345
                        index->n_user_defined_cols];
4465
4347
                n_vals = index->stat_n_diff_key_vals[1];
4466
4348
        }
4467
4349
 
4468
 
        dict_index_stat_mutex_exit(index);
 
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
        }
4469
4357
 
4470
4358
        fprintf(stderr,
4471
 
                "  INDEX: name %s, id %llu, fields %lu/%lu,"
 
4359
                "  INDEX: name %s, id %lu %lu, fields %lu/%lu,"
4472
4360
                " uniq %lu, type %lu\n"
4473
4361
                "   root page %lu, appr.key vals %lu,"
4474
4362
                " leaf pages %lu, size pages %lu\n"
4475
4363
                "   FIELDS: ",
4476
4364
                index->name,
4477
 
                (ullint) index->id,
 
4365
                (ulong) ut_dulint_get_high(index->id),
 
4366
                (ulong) ut_dulint_get_low(index->id),
4478
4367
                (ulong) index->n_user_defined_cols,
4479
4368
                (ulong) index->n_fields,
4480
4369
                (ulong) index->n_uniq,
4503
4392
void
4504
4393
dict_field_print_low(
4505
4394
/*=================*/
4506
 
        const dict_field_t*     field)  /*!< in: field */
 
4395
        dict_field_t*   field)  /*!< in: field */
4507
4396
{
4508
4397
        ut_ad(mutex_own(&(dict_sys->mutex)));
4509
4398
 
4753
4642
        dict_ind_redundant->cached = dict_ind_compact->cached = TRUE;
4754
4643
}
4755
4644
 
4756
 
/**********************************************************************//**
4757
 
Frees dict_ind_redundant and dict_ind_compact. */
4758
 
static
4759
 
void
4760
 
dict_ind_free(void)
4761
 
/*===============*/
4762
 
{
4763
 
        dict_table_t*   table;
4764
 
 
4765
 
        table = dict_ind_compact->table;
4766
 
        dict_mem_index_free(dict_ind_compact);
4767
 
        dict_ind_compact = NULL;
4768
 
        dict_mem_table_free(table);
4769
 
 
4770
 
        table = dict_ind_redundant->table;
4771
 
        dict_mem_index_free(dict_ind_redundant);
4772
 
        dict_ind_redundant = NULL;
4773
 
        dict_mem_table_free(table);
4774
 
}
4775
 
 
4776
4645
#ifndef UNIV_HOTBACKUP
4777
4646
/**********************************************************************//**
4778
4647
Get index by name
4846
4715
 
4847
4716
        while (index != NULL) {
4848
4717
                if (ut_strcmp(index->name, name) == 0) {
4849
 
                        if (!min_index || index->id < min_index->id) {
 
4718
                        if (!min_index
 
4719
                            || ut_dulint_cmp(index->id, min_index->id) < 0) {
4850
4720
 
4851
4721
                                min_index = index;
4852
4722
                        }
4866
4736
void
4867
4737
dict_table_check_for_dup_indexes(
4868
4738
/*=============================*/
4869
 
        const dict_table_t*     table,  /*!< in: Check for dup indexes
 
4739
        const dict_table_t*     table)  /*!< in: Check for dup indexes
4870
4740
                                        in this table */
4871
 
        ibool                   tmp_ok) /*!< in: TRUE=allow temporary
4872
 
                                        index names */
4873
4741
{
4874
4742
        /* Check for duplicates, ignoring indexes that are marked
4875
4743
        as to be dropped */
4877
4745
        const dict_index_t*     index1;
4878
4746
        const dict_index_t*     index2;
4879
4747
 
4880
 
        ut_ad(mutex_own(&dict_sys->mutex));
4881
 
 
4882
4748
        /* The primary index _must_ exist */
4883
4749
        ut_a(UT_LIST_GET_LEN(table->indexes) > 0);
4884
4750
 
4885
4751
        index1 = UT_LIST_GET_FIRST(table->indexes);
4886
 
 
4887
 
        do {
4888
 
                ut_ad(tmp_ok || *index1->name != TEMP_INDEX_PREFIX);
4889
 
 
4890
 
                index2 = UT_LIST_GET_NEXT(indexes, index1);
 
4752
        index2 = UT_LIST_GET_NEXT(indexes, index1);
 
4753
 
 
4754
        while (index1 && index2) {
4891
4755
 
4892
4756
                while (index2) {
4893
4757
 
4899
4763
                }
4900
4764
 
4901
4765
                index1 = UT_LIST_GET_NEXT(indexes, index1);
4902
 
        } while (index1);
 
4766
                index2 = UT_LIST_GET_NEXT(indexes, index1);
 
4767
        }
4903
4768
}
4904
4769
#endif /* UNIV_DEBUG */
4905
 
 
4906
 
/**************************************************************************
4907
 
Closes the data dictionary module. */
4908
 
UNIV_INTERN
4909
 
void
4910
 
dict_close(void)
4911
 
/*============*/
4912
 
{
4913
 
        ulint   i;
4914
 
 
4915
 
        /* Free the hash elements. We don't remove them from the table
4916
 
        because we are going to destroy the table anyway. */
4917
 
        for (i = 0; i < hash_get_n_cells(dict_sys->table_hash); i++) {
4918
 
                dict_table_t*   table;
4919
 
 
4920
 
                table = HASH_GET_FIRST(dict_sys->table_hash, i);
4921
 
 
4922
 
                while (table) {
4923
 
                        dict_table_t*   prev_table = table;
4924
 
 
4925
 
                        table = HASH_GET_NEXT(name_hash, prev_table);
4926
 
#ifdef UNIV_DEBUG
4927
 
                        ut_a(prev_table->magic_n == DICT_TABLE_MAGIC_N);
4928
 
#endif
4929
 
                        /* Acquire only because it's a pre-condition. */
4930
 
                        mutex_enter(&dict_sys->mutex);
4931
 
 
4932
 
                        dict_table_remove_from_cache(prev_table);
4933
 
 
4934
 
                        mutex_exit(&dict_sys->mutex);
4935
 
                }
4936
 
        }
4937
 
 
4938
 
        hash_table_free(dict_sys->table_hash);
4939
 
 
4940
 
        /* The elements are the same instance as in dict_sys->table_hash,
4941
 
        therefore we don't delete the individual elements. */
4942
 
        hash_table_free(dict_sys->table_id_hash);
4943
 
 
4944
 
        dict_ind_free();
4945
 
 
4946
 
        mutex_free(&dict_sys->mutex);
4947
 
 
4948
 
        rw_lock_free(&dict_operation_lock);
4949
 
        memset(&dict_operation_lock, 0x0, sizeof(dict_operation_lock));
4950
 
 
4951
 
        mutex_free(&dict_foreign_err_mutex);
4952
 
 
4953
 
        mem_free(dict_sys);
4954
 
        dict_sys = NULL;
4955
 
 
4956
 
        for (i = 0; i < DICT_INDEX_STAT_MUTEX_SIZE; i++) {
4957
 
                mutex_free(&dict_index_stat_mutex[i]);
4958
 
        }
4959
 
}
4960
4770
#endif /* !UNIV_HOTBACKUP */