1
1
/*****************************************************************************
3
Copyright (C) 1996, 2010, Innobase Oy. All Rights Reserved.
3
Copyright (c) 1996, 2010, 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
92
90
/** Identifies generated InnoDB foreign key names */
93
91
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];
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];
108
97
/*******************************************************************//**
109
98
Tries to find column names for the index and sets the col field of the
264
253
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])
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])
272
261
/**********************************************************************//**
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
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. */
278
dict_table_stats_lock(
279
/*==================*/
280
const dict_table_t* table, /*!< in: table */
281
ulint latch_mode) /*!< in: RW_S_LATCH or
267
dict_index_stat_mutex_enter(
268
/*========================*/
269
const dict_index_t* index) /*!< in: index */
284
ut_ad(table != NULL);
285
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
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);
287
switch (latch_mode) {
289
rw_lock_s_lock(GET_TABLE_STATS_LATCH(table));
292
rw_lock_x_lock(GET_TABLE_STATS_LATCH(table));
276
mutex_enter(GET_INDEX_STAT_MUTEX(index));
301
279
/**********************************************************************//**
302
Unlock the latch that has been locked by dict_table_stats_lock() */
280
Unlock the appropriate mutex that protects index->stat_n_diff_key_vals[]. */
305
dict_table_stats_unlock(
306
/*====================*/
307
const dict_table_t* table, /*!< in: table */
308
ulint latch_mode) /*!< in: RW_S_LATCH or
283
dict_index_stat_mutex_exit(
284
/*=======================*/
285
const dict_index_t* index) /*!< in: index */
311
ut_ad(table != NULL);
312
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
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);
314
switch (latch_mode) {
316
rw_lock_s_unlock(GET_TABLE_STATS_LATCH(table));
319
rw_lock_x_unlock(GET_TABLE_STATS_LATCH(table));
292
mutex_exit(GET_INDEX_STAT_MUTEX(index));
328
295
/********************************************************************//**
713
680
mutex_create(dict_foreign_err_mutex_key,
714
681
&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);
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);
722
689
/**********************************************************************//**
746
713
mutex_exit(&(dict_sys->mutex));
748
715
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 */);
716
if (!table->stat_initialized) {
717
/* If table->ibd_file_missing == TRUE, this will
718
print an error message and return without doing
720
dict_update_statistics(table);
1013
981
memory fragmentation, we assume a repeated calls of
1014
982
ut_realloc() with the same size do not cause fragmentation */
1015
983
ut_a(strlen(new_name) <= MAX_TABLE_NAME_LEN);
1016
table->name = static_cast<char *>(ut_realloc(table->name, MAX_TABLE_NAME_LEN + 1));
984
table->name = ut_realloc(table->name, MAX_TABLE_NAME_LEN + 1);
1018
986
memcpy(table->name, new_name, strlen(new_name) + 1);
1081
1049
TODO: store buf len to save memory */
1083
1051
foreign->foreign_table_name
1084
= static_cast<char *>(mem_heap_alloc(foreign->heap,
1085
ut_strlen(table->name) + 1));
1052
= mem_heap_alloc(foreign->heap,
1053
ut_strlen(table->name) + 1);
1088
1056
strcpy(foreign->foreign_table_name, table->name);
1124
1092
if (dict_get_db_name_len(table->name)
1125
1093
> dict_get_db_name_len(foreign->id)) {
1127
foreign->id = static_cast<char *>(mem_heap_alloc(
1095
foreign->id = mem_heap_alloc(
1129
db_len + strlen(old_id) + 1));
1097
db_len + strlen(old_id) + 1);
1132
1100
/* Replace the database prefix in id with the
1152
1120
/* Allocate a longer name buffer;
1153
1121
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));
1123
foreign->referenced_table_name = mem_heap_alloc(
1124
foreign->heap, strlen(table->name) + 1);
1159
1127
strcpy(foreign->referenced_table_name, table->name);
1682
1650
if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) {
1684
new_index->stat_n_diff_key_vals = static_cast<ib_int64_t *>(mem_heap_alloc(
1652
new_index->stat_n_diff_key_vals = mem_heap_alloc(
1685
1653
new_index->heap,
1686
1654
(1 + dict_index_get_n_unique(new_index))
1687
* sizeof(ib_int64_t)));
1655
* sizeof(ib_int64_t));
1688
1656
/* Give some sensible values to stat_n_... in case we do
1689
1657
not calculate statistics quickly enough */
2067
2035
/* 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);
2036
indexed = mem_zalloc(table->n_cols * sizeof *indexed);
2071
2038
/* Mark the table columns already contained in new_index */
2072
2039
for (i = 0; i < new_index->n_def; i++) {
2150
2117
dict_index_copy(new_index, index, table, 0, index->n_fields);
2152
2119
/* 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);
2120
indexed = mem_zalloc(table->n_cols * sizeof *indexed);
2156
2122
/* Mark the table columns already contained in new_index */
2157
2123
for (i = 0; i < new_index->n_def; i++) {
2861
2827
/* Convert the identifier from connection character set
2863
2829
len = 3 * len + 1;
2864
*id = dst = static_cast<char *>(mem_heap_alloc(heap, len));
2830
*id = dst = mem_heap_alloc(heap, len);
2866
2832
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())) {
2833
} else if (!strncmp(str, srv_mysql50_table_name_prefix,
2834
sizeof srv_mysql50_table_name_prefix)) {
2869
2835
/* This is a pre-5.1 table name
2870
2836
containing chars other than [A-Za-z0-9].
2871
2837
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();
2838
str += sizeof srv_mysql50_table_name_prefix;
2839
len -= sizeof srv_mysql50_table_name_prefix;
2874
2840
goto convert_id;
2876
2842
/* Encode using filename-safe characters. */
2877
2843
len = 5 * len + 1;
2878
*id = dst = static_cast<char *>(mem_heap_alloc(heap, len));
2844
*id = dst = mem_heap_alloc(heap, len);
2880
2846
innobase_convert_from_table_id(cs, dst, str, len);
3013
2979
table_name_len = strlen(table_name);
3015
2981
/* Copy database_name, '/', table_name, '\0' */
3016
ref = static_cast<char *>(mem_heap_alloc(heap, database_name_len + table_name_len + 2));
2982
ref = mem_heap_alloc(heap, database_name_len + table_name_len + 2);
3017
2983
memcpy(ref, database_name, database_name_len);
3018
2984
ref[database_name_len] = '/';
3019
2985
memcpy(ref + database_name_len + 1, table_name, table_name_len + 1);
3485
3451
start_of_latest_foreign);
3486
3452
mutex_exit(&dict_foreign_err_mutex);
3488
return(DB_CHILD_NO_INDEX);
3454
return(DB_CANNOT_ADD_CONSTRAINT);
3490
3456
ptr = dict_accept(cs, ptr, "REFERENCES", &success);
3510
3476
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));
3478
foreign->id = mem_heap_alloc(
3479
foreign->heap, db_len + strlen(constraint_name) + 2);
3515
3481
ut_memcpy(foreign->id, table->name, db_len);
3516
3482
foreign->id[db_len] = '/';
3523
3489
foreign->foreign_index = index;
3524
3490
foreign->n_fields = (unsigned int) i;
3525
foreign->foreign_col_names = static_cast<const char **>(mem_heap_alloc(foreign->heap,
3526
i * sizeof(void*)));
3491
foreign->foreign_col_names = mem_heap_alloc(foreign->heap,
3527
3493
for (i = 0; i < foreign->n_fields; i++) {
3528
3494
foreign->foreign_col_names[i] = mem_heap_strdup(
3779
3745
foreign->referenced_table_name
3780
3746
= 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*)));
3748
foreign->referenced_col_names = mem_heap_alloc(foreign->heap,
3784
3750
for (i = 0; i < foreign->n_fields; i++) {
3785
3751
foreign->referenced_col_names[i]
3786
3752
= mem_heap_strdup(foreign->heap, column_names[i]);
3838
3804
heap = mem_heap_create(10000);
3840
3806
err = dict_create_foreign_constraints_low(
3841
trx, heap, trx->session()->charset(), str, name,
3807
trx, heap, innobase_get_charset(trx->mysql_thd), str, name,
3844
3810
mem_heap_free(heap);
3877
3843
ut_a(trx->mysql_thd);
3879
cs = trx->session()->charset();
3845
cs = innobase_get_charset(trx->mysql_thd);
3883
*constraints_to_drop = static_cast<const char **>(mem_heap_alloc(heap, 1000 * sizeof(char*)));
3849
*constraints_to_drop = mem_heap_alloc(heap, 1000 * sizeof(char*));
3885
ptr= trx->session()->getQueryStringCopy(len);
3851
ptr = innobase_get_stmt(trx->mysql_thd, &len);
3887
3853
str = dict_strip_comments(ptr, len);
4098
4064
dict_index_copy_types(tuple, index, n_unique);
4100
buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
4066
buf = mem_heap_alloc(heap, 4);
4102
4068
mach_write_to_4(buf, page_no);
4230
4196
are used in query optimization. */
4233
dict_update_statistics(
4234
/*===================*/
4199
dict_update_statistics_low(
4200
/*=======================*/
4235
4201
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
4202
ibool has_dict_mutex __attribute__((unused)))
4203
/*!< in: TRUE if the caller has the
4241
4206
dict_index_t* index;
4242
4207
ulint sum_of_index_sizes = 0;
4316
4275
index = dict_table_get_first_index(table);
4277
dict_index_stat_mutex_enter(index);
4318
4279
table->stat_n_rows = index->stat_n_diff_key_vals[
4319
4280
dict_index_get_n_unique(index)];
4282
dict_index_stat_mutex_exit(index);
4321
4284
table->stat_clustered_index_size = index->stat_index_size;
4323
4286
table->stat_sum_of_other_index_sizes = sum_of_index_sizes
4326
4289
table->stat_initialized = TRUE;
4328
4291
table->stat_modified_counter = 0;
4330
dict_table_stats_unlock(table, RW_X_LATCH);
4294
/*********************************************************************//**
4295
Calculates new estimates for table and index statistics. The statistics
4296
are used in query optimization. */
4299
dict_update_statistics(
4300
/*===================*/
4301
dict_table_t* table) /*!< in/out: table */
4303
dict_update_statistics_low(table, FALSE);
4333
4306
/**********************************************************************//**
4408
4381
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);
4383
dict_update_statistics_low(table, TRUE);
4414
4385
fprintf(stderr,
4415
4386
"--------------------------------------\n"
4836
4809
dict_table_replace_index_in_foreign_list(
4837
4810
/*=====================================*/
4838
4811
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 */
4812
dict_index_t* index) /*!< in: index to be replaced */
4842
4814
dict_foreign_t* foreign;
4848
4820
if (foreign->foreign_index == index) {
4849
4821
dict_index_t* new_index
4850
4822
= 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
4825
foreign->foreign_index = new_index;
4951
4917
for (i = 0; i < hash_get_n_cells(dict_sys->table_hash); i++) {
4952
4918
dict_table_t* table;
4954
table = static_cast<dict_table_t *>(HASH_GET_FIRST(dict_sys->table_hash, i));
4920
table = HASH_GET_FIRST(dict_sys->table_hash, i);
4956
4922
while (table) {
4957
4923
dict_table_t* prev_table = table;
4959
table = static_cast<dict_table_t *>(HASH_GET_NEXT(name_hash, prev_table));
4925
table = HASH_GET_NEXT(name_hash, prev_table);
4960
4926
#ifdef UNIV_DEBUG
4961
4927
ut_a(prev_table->magic_n == DICT_TABLE_MAGIC_N);