1
1
/*****************************************************************************
3
Copyright (C) 1996, 2010, Innobase Oy. All Rights Reserved.
3
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
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.
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
17
17
*****************************************************************************/
71
69
on the mode in trx_struct::dict_operation_lock_mode */
72
70
UNIV_INTERN rw_lock_t dict_operation_lock;
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 */
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 */
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_";
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];
108
82
/*******************************************************************//**
109
83
Tries to find column names for the index and sets the col field of the
111
@return TRUE if the column names were found */
114
87
dict_index_find_cols(
115
88
/*=================*/
116
89
dict_table_t* table, /*!< in: table */
264
237
mutex_exit(&(dict_sys->mutex));
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])
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
278
dict_table_stats_lock(
279
/*==================*/
280
const dict_table_t* table, /*!< in: table */
281
ulint latch_mode) /*!< in: RW_S_LATCH or
284
ut_ad(table != NULL);
285
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
287
switch (latch_mode) {
289
rw_lock_s_lock(GET_TABLE_STATS_LATCH(table));
292
rw_lock_x_lock(GET_TABLE_STATS_LATCH(table));
301
/**********************************************************************//**
302
Unlock the latch that has been locked by dict_table_stats_lock() */
305
dict_table_stats_unlock(
306
/*====================*/
307
const dict_table_t* table, /*!< in: table */
308
ulint latch_mode) /*!< in: RW_S_LATCH or
311
ut_ad(table != NULL);
312
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
314
switch (latch_mode) {
316
rw_lock_s_unlock(GET_TABLE_STATS_LATCH(table));
319
rw_lock_x_unlock(GET_TABLE_STATS_LATCH(table));
328
240
/********************************************************************//**
329
241
Decrements the count of open MySQL handles to a table. */
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 */
462
374
dict_index_t* index;
464
376
index = dict_table_get_first_index(table);
467
if (id == index->id) {
379
if (0 == ut_dulint_cmp(id, index->id)) {
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 */
612
524
dict_table_t* table;
614
if (trx->dict_operation_lock_mode == RW_X_LATCH) {
616
/* Note: An X latch implies that the transaction
617
already owns the dictionary mutex. */
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! */
533
ut_ad(mutex_own(&(dict_sys->mutex))
534
|| trx->dict_operation_lock_mode == RW_X_LATCH);
621
536
return(dict_table_get_on_id_low(table_id));
693
dict_sys = static_cast<dict_sys_t *>(mem_alloc(sizeof(dict_sys_t)));
695
mutex_create(dict_sys_mutex_key, &dict_sys->mutex, SYNC_DICT);
606
dict_sys = mem_alloc(sizeof(dict_sys_t));
608
mutex_create(&dict_sys->mutex, SYNC_DICT);
697
610
dict_sys->table_hash = hash_create(buf_pool_get_curr_size()
698
611
/ (DICT_POOL_PER_TABLE_HASH
705
618
UT_LIST_INIT(dict_sys->table_LRU);
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);
710
622
dict_foreign_err_file = os_file_create_tmpfile();
711
623
ut_a(dict_foreign_err_file);
713
mutex_create(dict_foreign_err_mutex_key,
714
&dict_foreign_err_mutex, SYNC_ANY_LATCH);
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);
625
mutex_create(&dict_foreign_err_mutex, SYNC_ANY_LATCH);
722
628
/**********************************************************************//**
746
652
mutex_exit(&(dict_sys->mutex));
748
654
if (table != NULL) {
749
/* If table->ibd_file_missing == TRUE, this will
750
print an error message and return without doing
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
659
dict_update_statistics(table);
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);
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);
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);
899
805
/**********************************************************************//**
947
853
dict_foreign_t* foreign;
948
854
dict_index_t* index;
950
char old_name[MAX_TABLE_NAME_LEN + 1];
857
const char* old_name;
953
860
ut_ad(mutex_own(&(dict_sys->mutex)));
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);
959
ut_print_timestamp(stderr);
960
fprintf(stderr, "InnoDB: too long table name: '%s', "
961
"max length is %d\n", table->name,
862
old_size = mem_heap_get_size(table->heap);
863
old_name = table->name;
966
865
fold = ut_fold_string(new_name);
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);
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));
1018
memcpy(table->name, new_name, strlen(new_name) + 1);
909
table->name = mem_heap_strdup(table->heap, new_name);
1020
911
/* Add table to hash table of tables */
1021
912
HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold,
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);
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 */
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);
1088
977
strcpy(foreign->foreign_table_name, table->name);
1105
994
/* This is a generated >= 4.0.18 format id */
1107
996
if (strlen(table->name) > strlen(old_name)) {
1108
foreign->id = static_cast<char *>(mem_heap_alloc(
997
foreign->id = mem_heap_alloc(
1110
999
strlen(table->name)
1111
+ strlen(old_id) + 1));
1000
+ strlen(old_id) + 1);
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)) {
1127
foreign->id = static_cast<char *>(mem_heap_alloc(
1016
foreign->id = mem_heap_alloc(
1129
db_len + strlen(old_id) + 1));
1018
db_len + strlen(old_id) + 1);
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 */
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);
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 */
1178
1067
ut_ad(mutex_own(&(dict_sys->mutex)));
1181
1070
/* Remove the table from the hash table of id's */
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;
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);
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);
1247
1136
/* Remove table from LRU list of tables */
1248
1137
UT_LIST_REMOVE(table_LRU, dict_sys->table_LRU, table);
1250
size = mem_heap_get_size(table->heap) + strlen(table->name) + 1;
1139
size = mem_heap_get_size(table->heap);
1252
1141
ut_ad(dict_sys->size >= size);
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 */
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 */
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);
1570
if (!dict_index_find_cols(table, index)) {
1572
dict_mem_index_free(index);
1573
return(DB_CORRUPTION);
1459
dict_index_find_cols(table, index);
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;
1678
1563
new_index->page = page_no;
1679
rw_lock_create(index_tree_rw_lock_key, &new_index->lock,
1564
rw_lock_create(&new_index->lock, SYNC_INDEX_TREE);
1682
1566
if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) {
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 */
1781
1665
/*******************************************************************//**
1782
1666
Tries to find column names for the index and sets the col field of the
1784
@return TRUE if the column names were found */
1787
1670
dict_index_find_cols(
1788
1671
/*=================*/
1789
1672
dict_table_t* table, /*!< in: table */
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 */
1827
1706
#endif /* !UNIV_HOTBACKUP */
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);
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);
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);
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*/
2509
if (!found || index->id > found->id) {
2387
|| ut_dulint_cmp(index->id, found->id) > 0) {
2861
2739
/* Convert the identifier from connection character set
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);
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;
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);
2880
2758
innobase_convert_from_table_id(cs, dst, str, len);
3013
2891
table_name_len = strlen(table_name);
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);
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 */
3077
2954
const char* sptr;
3078
const char* eptr = sql_string + sql_length;
3080
2956
/* unclosed quote character (0 if none) */
3081
2957
char quote = 0;
3083
str = static_cast<char *>(mem_alloc(sql_length + 1));
2959
str = mem_alloc(strlen(sql_string) + 1);
3085
2961
sptr = sql_string;
3090
if (sptr >= eptr || *sptr == '\0') {
2966
if (*sptr == '\0') {
3094
ut_a(ptr <= str + sql_length);
2969
ut_a(ptr <= str + strlen(sql_string));
3110
2985
|| (sptr[0] == '-' && sptr[1] == '-'
3111
2986
&& sptr[2] == ' ')) {
3113
if (++sptr >= eptr) {
3117
2988
/* In Unix a newline is 0x0A while in Windows
3118
2989
it is 0x0D followed by 0x0A */
2991
if (*sptr == (char)0x0A
2992
|| *sptr == (char)0x0D
3124
2995
goto scan_more;
3127
3000
} else if (!quote && *sptr == '/' && *(sptr + 1) == '*') {
3002
if (*sptr == '*' && *(sptr + 1) == '/') {
3009
if (*sptr == '\0') {
3136
3011
goto scan_more;
3138
if (sptr[1] == '/') {
3485
3355
start_of_latest_foreign);
3486
3356
mutex_exit(&dict_foreign_err_mutex);
3488
return(DB_CHILD_NO_INDEX);
3358
return(DB_CANNOT_ADD_CONSTRAINT);
3490
3360
ptr = dict_accept(cs, ptr, "REFERENCES", &success);
3510
3380
db_len = dict_get_db_name_len(table->name);
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);
3515
3385
ut_memcpy(foreign->id, table->name, db_len);
3516
3386
foreign->id[db_len] = '/';
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,
3527
3397
for (i = 0; i < foreign->n_fields; i++) {
3528
3398
foreign->foreign_col_names[i] = mem_heap_strdup(
3766
3636
start_of_latest_foreign);
3767
3637
mutex_exit(&dict_foreign_err_mutex);
3769
return(DB_PARENT_NO_INDEX);
3639
return(DB_CANNOT_ADD_CONSTRAINT);
3772
3642
ut_a(trx->check_foreigns == FALSE);
3779
3649
foreign->referenced_table_name
3780
3650
= mem_heap_strdup(foreign->heap, referenced_table_name);
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,
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 */
3835
3704
ut_a(trx->mysql_thd);
3837
str = dict_strip_comments(sql_string, sql_length);
3706
str = dict_strip_comments(sql_string);
3838
3707
heap = mem_heap_create(10000);
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,
3844
3713
mem_heap_free(heap);
3877
3745
ut_a(trx->mysql_thd);
3879
cs = trx->session()->charset();
3747
cs = innobase_get_charset(trx->mysql_thd);
3883
*constraints_to_drop = static_cast<const char **>(mem_heap_alloc(heap, 1000 * sizeof(char*)));
3885
ptr= trx->session()->getQueryStringCopy(len);
3887
str = dict_strip_comments(ptr, len);
3751
*constraints_to_drop = mem_heap_alloc(heap, 1000 * sizeof(char*));
3753
str = dict_strip_comments((trx->mysql_query_str));
3891
3756
ut_ad(mutex_own(&(dict_sys->mutex)));
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 */
3999
3864
ut_ad(mutex_own(&(dict_sys->mutex)));
4098
3963
dict_index_copy_types(tuple, index, n_unique);
4100
buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
3965
buf = mem_heap_alloc(heap, 4);
4102
3967
mach_write_to_4(buf, page_no);
4230
4095
are used in query optimization. */
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
4101
ibool has_dict_mutex __attribute__((unused)))
4102
/*!< in: TRUE if the caller has the
4241
4105
dict_index_t* index;
4242
4107
ulint sum_of_index_sizes = 0;
4244
4109
if (table->ibd_file_missing) {
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. */
4124
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
4256
4129
/* Find out the sizes of the indexes and how many different values
4257
4130
for the key they approximately have */
4267
dict_table_stats_lock(table, RW_X_LATCH);
4269
if (only_calc_if_missing_stats && table->stat_initialized) {
4270
dict_table_stats_unlock(table, RW_X_LATCH);
4276
(srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE
4277
|| (srv_force_recovery < SRV_FORCE_NO_LOG_REDO
4278
&& dict_index_is_clust(index)))) {
4280
size = btr_get_size(index, BTR_TOTAL_SIZE);
4282
index->stat_index_size = size;
4284
sum_of_index_sizes += size;
4286
size = btr_get_size(index, BTR_N_LEAF_PAGES);
4289
/* The root node of the tree is a leaf */
4293
index->stat_n_leaf_pages = size;
4295
btr_estimate_number_of_different_key_vals(index);
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. */
4305
sum_of_index_sizes++;
4306
index->stat_index_size = index->stat_n_leaf_pages = 1;
4308
for (i = dict_index_get_n_unique(index); i; ) {
4309
index->stat_n_diff_key_vals[i--] = 1;
4141
size = btr_get_size(index, BTR_TOTAL_SIZE);
4143
index->stat_index_size = size;
4145
sum_of_index_sizes += size;
4147
size = btr_get_size(index, BTR_N_LEAF_PAGES);
4150
/* The root node of the tree is a leaf */
4154
index->stat_n_leaf_pages = size;
4156
btr_estimate_number_of_different_key_vals(index);
4313
4158
index = dict_table_get_next_index(index);
4316
4161
index = dict_table_get_first_index(table);
4326
4171
table->stat_initialized = TRUE;
4328
4173
table->stat_modified_counter = 0;
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. */
4181
dict_update_statistics(
4182
/*===================*/
4183
dict_table_t* table) /*!< in/out: table */
4185
dict_update_statistics_low(table, FALSE);
4333
4188
/**********************************************************************//**
4408
4263
ut_ad(mutex_own(&(dict_sys->mutex)));
4410
dict_update_statistics(table, FALSE /* update even if initialized */);
4412
dict_table_stats_lock(table, RW_S_LATCH);
4265
dict_update_statistics_low(table, TRUE);
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"
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);
4440
dict_table_stats_unlock(table, RW_S_LATCH);
4442
4294
foreign = UT_LIST_GET_FIRST(table->foreign_list);
4444
4296
while (foreign != NULL) {
4494
4347
n_vals = index->stat_n_diff_key_vals[1];
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";
4355
type_string = "secondary index";
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"
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,
4780
4642
dict_ind_redundant->cached = dict_ind_compact->cached = TRUE;
4783
/**********************************************************************//**
4784
Frees dict_ind_redundant and dict_ind_compact. */
4790
dict_table_t* table;
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);
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);
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 */
4842
4683
dict_foreign_t* foreign;
4848
4689
if (foreign->foreign_index == index) {
4849
4690
dict_index_t* new_index
4850
4691
= dict_foreign_find_equiv_index(foreign);
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. */
4857
ut_a(new_index || !trx->check_foreigns);
4859
4694
foreign->foreign_index = new_index;
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
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;
4914
ut_ad(mutex_own(&dict_sys->mutex));
4916
4748
/* The primary index _must_ exist */
4917
4749
ut_a(UT_LIST_GET_LEN(table->indexes) > 0);
4919
4751
index1 = UT_LIST_GET_FIRST(table->indexes);
4922
ut_ad(tmp_ok || *index1->name != TEMP_INDEX_PREFIX);
4924
index2 = UT_LIST_GET_NEXT(indexes, index1);
4752
index2 = UT_LIST_GET_NEXT(indexes, index1);
4754
while (index1 && index2) {
4926
4756
while (index2) {
4935
4765
index1 = UT_LIST_GET_NEXT(indexes, index1);
4766
index2 = UT_LIST_GET_NEXT(indexes, index1);
4938
4769
#endif /* UNIV_DEBUG */
4940
/**************************************************************************
4941
Closes the data dictionary module. */
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;
4954
table = static_cast<dict_table_t *>(HASH_GET_FIRST(dict_sys->table_hash, i));
4957
dict_table_t* prev_table = table;
4959
table = static_cast<dict_table_t *>(HASH_GET_NEXT(name_hash, prev_table));
4961
ut_a(prev_table->magic_n == DICT_TABLE_MAGIC_N);
4963
/* Acquire only because it's a pre-condition. */
4964
mutex_enter(&dict_sys->mutex);
4966
dict_table_remove_from_cache(prev_table);
4968
mutex_exit(&dict_sys->mutex);
4972
hash_table_free(dict_sys->table_hash);
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);
4980
mutex_free(&dict_sys->mutex);
4982
rw_lock_free(&dict_operation_lock);
4983
memset(&dict_operation_lock, 0x0, sizeof(dict_operation_lock));
4985
mutex_free(&dict_foreign_err_mutex);
4990
for (i = 0; i < DICT_TABLE_STATS_LATCHES_SIZE; i++) {
4991
rw_lock_free(&dict_table_stats_latches[i]);
4994
4770
#endif /* !UNIV_HOTBACKUP */