52
29
#include "que0que.h"
53
30
#include "rem0cmp.h"
54
31
#include "row0merge.h"
55
#include "ha_prototypes.h" /* innobase_strcasecmp() */
32
#ifndef UNIV_HOTBACKUP
33
# if defined(BUILD_DRIZZLE)
34
# include <mystrings/m_ctype.h>
36
# include "m_ctype.h" /* my_isspace() */
38
# include "ha_prototypes.h" /* innobase_strcasecmp() */
39
#endif /* !UNIV_HOTBACKUP */
59
#include <drizzled/session.h>
61
/** the dictionary system */
43
/* the dictionary system */
62
44
UNIV_INTERN dict_sys_t* dict_sys = NULL;
64
/** @brief the data dictionary rw-latch protecting dict_sys
66
table create, drop, etc. reserve this in X-mode; implicit or
46
/* table create, drop, etc. reserve this in X-mode; implicit or
67
47
backround operations purge, rollback, foreign key checks reserve this
68
48
in S-mode; we cannot trust that MySQL protects implicit or background
69
49
operations a table drop since MySQL does not know of them; therefore
70
50
we need this; NOTE: a transaction which reserves this must keep book
71
on the mode in trx_struct::dict_operation_lock_mode */
51
on the mode in trx->dict_operation_lock_mode */
72
52
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
#define DICT_HEAP_SIZE 100 /*!< initial memory heap size when
86
creating a table or index object */
87
#define DICT_POOL_PER_TABLE_HASH 512 /*!< buffer pool max size per table
54
#define DICT_POOL_PER_TABLE_HASH 512 /* buffer pool max size per table
88
55
hash table fixed size in bytes */
89
#define DICT_POOL_PER_VARYING 4 /*!< buffer pool max size per data
90
dictionary varying size in bytes */
92
/** Identifies generated InnoDB foreign key names */
57
/* Identifies generated InnoDB foreign key names */
93
58
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
/*******************************************************************//**
60
/***********************************************************************
109
61
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
65
dict_index_find_cols(
115
66
/*=================*/
116
dict_table_t* table, /*!< in: table */
117
dict_index_t* index); /*!< in: index */
118
/*******************************************************************//**
67
dict_table_t* table, /* in: table */
68
dict_index_t* index); /* in: index */
69
/***********************************************************************
119
70
Builds the internal dictionary cache representation for a clustered
120
index, containing also system fields not defined by the user.
121
@return own: the internal representation of the clustered index */
71
index, containing also system fields not defined by the user. */
124
74
dict_index_build_internal_clust(
125
75
/*============================*/
126
const dict_table_t* table, /*!< in: table */
127
dict_index_t* index); /*!< in: user representation of
76
/* out, own: the internal
77
representation of the clustered
79
const dict_table_t* table, /* in: table */
80
dict_index_t* index); /* in: user representation of
128
81
a clustered index */
129
/*******************************************************************//**
82
/***********************************************************************
130
83
Builds the internal dictionary cache representation for a non-clustered
131
index, containing also system fields not defined by the user.
132
@return own: the internal representation of the non-clustered index */
84
index, containing also system fields not defined by the user. */
135
87
dict_index_build_internal_non_clust(
136
88
/*================================*/
137
const dict_table_t* table, /*!< in: table */
138
dict_index_t* index); /*!< in: user representation of
89
/* out, own: the internal
90
representation of the non-clustered
92
const dict_table_t* table, /* in: table */
93
dict_index_t* index); /* in: user representation of
139
94
a non-clustered index */
140
/**********************************************************************//**
95
/**************************************************************************
141
96
Removes a foreign constraint struct from the dictionary cache. */
144
99
dict_foreign_remove_from_cache(
145
100
/*===========================*/
146
dict_foreign_t* foreign); /*!< in, own: foreign constraint */
147
/**********************************************************************//**
101
dict_foreign_t* foreign); /* in, own: foreign constraint */
102
/**************************************************************************
148
103
Prints a column data. */
151
106
dict_col_print_low(
152
107
/*===============*/
153
const dict_table_t* table, /*!< in: table */
154
const dict_col_t* col); /*!< in: column */
155
/**********************************************************************//**
108
const dict_table_t* table, /* in: table */
109
const dict_col_t* col); /* in: column */
110
/**************************************************************************
156
111
Prints an index data. */
159
114
dict_index_print_low(
160
115
/*=================*/
161
dict_index_t* index); /*!< in: index */
162
/**********************************************************************//**
116
dict_index_t* index); /* in: index */
117
/**************************************************************************
163
118
Prints a field data. */
166
121
dict_field_print_low(
167
122
/*=================*/
168
const dict_field_t* field); /*!< in: field */
169
/*********************************************************************//**
123
dict_field_t* field); /* in: field */
124
/*************************************************************************
170
125
Frees a foreign key struct. */
173
128
dict_foreign_free(
174
129
/*==============*/
175
dict_foreign_t* foreign); /*!< in, own: foreign key struct */
130
dict_foreign_t* foreign); /* in, own: foreign key struct */
177
132
/* Stream for storing detailed information about the latest foreign key
178
133
and unique key errors */
180
135
/* mutex protecting the foreign and unique error buffers */
181
136
UNIV_INTERN mutex_t dict_foreign_err_mutex;
183
/******************************************************************//**
138
#ifndef UNIV_HOTBACKUP
139
/**********************************************************************
184
140
Makes all characters in a NUL-terminated UTF-8 string lower case. */
189
char* a) /*!< in/out: string to put in lower case */
145
char* a) /* in/out: string to put in lower case */
191
147
innobase_casedn_str(a);
149
#endif /* !UNIV_HOTBACKUP */
194
/********************************************************************//**
195
Checks if the database name in two table names is the same.
196
@return TRUE if same db name */
151
/************************************************************************
152
Checks if the database name in two table names is the same. */
199
155
dict_tables_have_same_db(
200
156
/*=====================*/
201
const char* name1, /*!< in: table name in the form
157
/* out: TRUE if same db name */
158
const char* name1, /* in: table name in the form
202
159
dbname '/' tablename */
203
const char* name2) /*!< in: table name in the form
160
const char* name2) /* in: table name in the form
204
161
dbname '/' tablename */
206
163
for (; *name1 == *name2; name1++, name2++) {
264
221
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
/********************************************************************//**
224
/************************************************************************
329
225
Decrements the count of open MySQL handles to a table. */
332
228
dict_table_decrement_handle_count(
333
229
/*==============================*/
334
dict_table_t* table, /*!< in/out: table */
335
ibool dict_locked) /*!< in: TRUE=data dictionary locked */
230
dict_table_t* table, /* in/out: table */
231
ibool dict_locked) /* in: TRUE=data dictionary locked */
337
233
if (!dict_locked) {
338
234
mutex_enter(&dict_sys->mutex);
380
#ifndef UNIV_HOTBACKUP
381
/********************************************************************//**
382
Acquire the autoinc lock. */
278
/************************************************************************
279
Acquire the autoinc lock.*/
385
282
dict_table_autoinc_lock(
386
283
/*====================*/
387
dict_table_t* table) /*!< in/out: table */
284
dict_table_t* table) /* in/out: table */
389
286
mutex_enter(&table->autoinc_mutex);
392
/********************************************************************//**
289
/************************************************************************
393
290
Unconditionally set the autoinc counter. */
396
293
dict_table_autoinc_initialize(
397
294
/*==========================*/
398
dict_table_t* table, /*!< in/out: table */
399
ib_uint64_t value) /*!< in: next value to assign to a row */
295
dict_table_t* table, /* in/out: table */
296
ib_uint64_t value) /* in: next value to assign to a row */
401
298
ut_ad(mutex_own(&table->autoinc_mutex));
403
300
table->autoinc = value;
406
/********************************************************************//**
303
/************************************************************************
407
304
Reads the next autoinc value (== autoinc counter value), 0 if not yet
409
@return value for a new row, or 0 */
412
308
dict_table_autoinc_read(
413
309
/*====================*/
414
const dict_table_t* table) /*!< in: table */
310
/* out: value for a new row, or 0 */
311
const dict_table_t* table) /* in: table */
416
313
ut_ad(mutex_own(&table->autoinc_mutex));
418
315
return(table->autoinc);
421
/********************************************************************//**
318
/************************************************************************
422
319
Updates the autoinc counter if the value supplied is greater than the
423
320
current value. */
440
/********************************************************************//**
441
Release the autoinc lock. */
337
/************************************************************************
338
Release the autoinc lock.*/
444
341
dict_table_autoinc_unlock(
445
342
/*======================*/
446
dict_table_t* table) /*!< in/out: table */
343
dict_table_t* table) /* in/out: table */
448
345
mutex_exit(&table->autoinc_mutex);
451
/**********************************************************************//**
348
/**************************************************************************
452
349
Looks for an index with the given table and index id.
453
NOTE that we do not reserve the dictionary mutex.
454
@return index or NULL if not found from cache */
350
NOTE that we do not reserve the dictionary mutex. */
457
353
dict_index_get_on_id_low(
458
354
/*=====================*/
459
dict_table_t* table, /*!< in: table */
460
index_id_t id) /*!< in: index id */
355
/* out: index or NULL if not found
357
dict_table_t* table, /* in: table */
358
dulint id) /* in: index id */
462
360
dict_index_t* index;
464
362
index = dict_table_get_first_index(table);
467
if (id == index->id) {
365
if (0 == ut_dulint_cmp(id, index->id)) {
560
/********************************************************************//**
459
/************************************************************************
561
460
Looks for a matching field in an index. The column has to be the same. The
562
461
column in index must be complete, or must contain a prefix longer than the
563
462
column in index2. That is, we must be able to construct the prefix in index2
564
from the prefix in index.
565
@return position in internal representation of the index;
566
ULINT_UNDEFINED if not contained */
463
from the prefix in index. */
569
466
dict_index_get_nth_field_pos(
570
467
/*=========================*/
571
const dict_index_t* index, /*!< in: index from which to search */
572
const dict_index_t* index2, /*!< in: index */
573
ulint n) /*!< in: field number in index2 */
468
/* out: position in internal
469
representation of the index;
470
if not contained, returns
472
const dict_index_t* index, /* in: index from which to search */
473
const dict_index_t* index2, /* in: index */
474
ulint n) /* in: field number in index2 */
575
476
const dict_field_t* field;
576
477
const dict_field_t* field2;
599
500
return(ULINT_UNDEFINED);
602
/**********************************************************************//**
603
Returns a table object based on table id.
604
@return table, NULL if does not exist */
503
/**************************************************************************
504
Returns a table object based on table id. */
607
507
dict_table_get_on_id(
608
508
/*=================*/
609
table_id_t table_id, /*!< in: table id */
610
trx_t* trx) /*!< in: transaction handle */
509
/* out: table, NULL if does not exist */
510
dulint table_id, /* in: table id */
511
trx_t* trx) /* in: transaction handle */
612
513
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));
515
if (ut_dulint_cmp(table_id, DICT_FIELDS_ID) <= 0
516
|| trx->dict_operation_lock_mode == RW_X_LATCH) {
517
/* It is a system table which will always exist in the table
518
cache: we avoid acquiring the dictionary mutex, because
519
if we are doing a rollback to handle an error in TABLE
520
CREATE, for example, we already have the mutex! */
522
ut_ad(mutex_own(&(dict_sys->mutex))
523
|| trx->dict_operation_lock_mode == RW_X_LATCH);
621
525
return(dict_table_get_on_id_low(table_id));
633
/********************************************************************//**
634
Looks for column n position in the clustered index.
635
@return position in internal representation of the clustered index */
537
/************************************************************************
538
Looks for column n position in the clustered index. */
638
541
dict_table_get_nth_col_pos(
639
542
/*=======================*/
640
const dict_table_t* table, /*!< in: table */
641
ulint n) /*!< in: column number */
543
/* out: position in internal
545
the clustered index */
546
const dict_table_t* table, /* in: table */
547
ulint n) /* in: column number */
643
549
return(dict_index_get_nth_col_pos(dict_table_get_first_index(table),
647
/********************************************************************//**
553
/************************************************************************
648
554
Checks if a column is in the ordering columns of the clustered index of a
649
table. Column prefixes are treated like whole columns.
650
@return TRUE if the column, or its prefix, is in the clustered key */
555
table. Column prefixes are treated like whole columns. */
653
558
dict_table_col_in_clustered_key(
654
559
/*============================*/
655
const dict_table_t* table, /*!< in: table */
656
ulint n) /*!< in: column number */
560
/* out: TRUE if the column, or its
561
prefix, is in the clustered key */
562
const dict_table_t* table, /* in: table */
563
ulint n) /* in: column number */
658
565
const dict_index_t* index;
659
566
const dict_field_t* field;
705
610
UT_LIST_INIT(dict_sys->table_LRU);
707
rw_lock_create(dict_operation_lock_key,
708
&dict_operation_lock, SYNC_DICT_OPERATION);
612
rw_lock_create(&dict_operation_lock, SYNC_DICT_OPERATION);
710
614
dict_foreign_err_file = os_file_create_tmpfile();
711
615
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);
617
mutex_create(&dict_foreign_err_mutex, SYNC_ANY_LATCH);
722
/**********************************************************************//**
620
/**************************************************************************
723
621
Returns a table object and optionally increment its MySQL open handle count.
724
622
NOTE! This is a high-level function to be used mainly from outside the
725
623
'dict' directory. Inside this directory dict_table_get_low is usually the
726
appropriate function.
727
@return table, NULL if does not exist */
624
appropriate function. */
732
const char* table_name, /*!< in: table name */
733
ibool inc_mysql_count)/*!< in: whether to increment the open
629
/* out: table, NULL if
631
const char* table_name, /* in: table name */
632
ibool inc_mysql_count)
633
/* in: whether to increment the open
734
634
handle count on the table */
736
636
dict_table_t* table;
746
646
mutex_exit(&(dict_sys->mutex));
748
648
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 */);
649
if (!table->stat_initialized) {
650
/* If table->ibd_file_missing == TRUE, this will
651
print an error message and return without doing
653
dict_update_statistics(table);
758
#endif /* !UNIV_HOTBACKUP */
760
/**********************************************************************//**
660
/**************************************************************************
761
661
Adds system columns to a table object. */
764
664
dict_table_add_system_columns(
765
665
/*==========================*/
766
dict_table_t* table, /*!< in/out: table */
767
mem_heap_t* heap) /*!< in: temporary heap */
666
dict_table_t* table, /* in/out: table */
667
mem_heap_t* heap) /* in: temporary heap */
770
670
ut_ad(table->n_def == table->n_cols - DATA_N_SYS_COLS);
853
752
dict_table_t* table2;
854
753
HASH_SEARCH(name_hash, dict_sys->table_hash, fold,
855
dict_table_t*, table2, ut_ad(table2->cached),
856
ut_strcmp(table2->name, table->name) == 0);
754
dict_table_t*, table2,
755
(ut_strcmp(table2->name, table->name) == 0));
857
756
ut_a(table2 == NULL);
860
/* Look for the same table pointer with a different name */
861
HASH_SEARCH_ALL(name_hash, dict_sys->table_hash,
862
dict_table_t*, table2, ut_ad(table2->cached),
864
ut_ad(table2 == NULL);
865
#endif /* UNIV_DEBUG */
868
759
/* Look for a table with the same id: error if such exists */
870
761
dict_table_t* table2;
871
762
HASH_SEARCH(id_hash, dict_sys->table_id_hash, id_fold,
872
dict_table_t*, table2, ut_ad(table2->cached),
873
table2->id == table->id);
763
dict_table_t*, table2,
764
(ut_dulint_cmp(table2->id, table->id) == 0));
874
765
ut_a(table2 == NULL);
877
/* Look for the same table pointer with a different id */
878
HASH_SEARCH_ALL(id_hash, dict_sys->table_id_hash,
879
dict_table_t*, table2, ut_ad(table2->cached),
881
ut_ad(table2 == NULL);
882
#endif /* UNIV_DEBUG */
885
768
/* Add table to hash table of tables */
934
/**********************************************************************//**
935
Renames a table object.
936
@return TRUE if success */
816
/**************************************************************************
817
Renames a table object. */
939
820
dict_table_rename_in_cache(
940
821
/*=======================*/
941
dict_table_t* table, /*!< in/out: table */
942
const char* new_name, /*!< in: new name */
943
ibool rename_also_foreigns)/*!< in: in ALTER TABLE we want
822
/* out: TRUE if success */
823
dict_table_t* table, /* in/out: table */
824
const char* new_name, /* in: new name */
825
ibool rename_also_foreigns)/* in: in ALTER TABLE we want
944
826
to preserve the original table name
945
827
in constraints which reference it */
947
829
dict_foreign_t* foreign;
948
830
dict_index_t* index;
950
char old_name[MAX_TABLE_NAME_LEN + 1];
833
const char* old_name;
953
836
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,
838
old_size = mem_heap_get_size(table->heap);
839
old_name = table->name;
966
841
fold = ut_fold_string(new_name);
1007
882
/* Remove table from the hash tables of tables */
1008
883
HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash,
1009
884
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);
885
table->name = mem_heap_strdup(table->heap, new_name);
1020
887
/* Add table to hash table of tables */
1021
888
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);
890
dict_sys->size += (mem_heap_get_size(table->heap) - old_size);
1027
892
/* Update the table_name field in indexes */
1028
893
index = dict_table_get_first_index(table);
2201
2050
/*====================== FOREIGN KEY PROCESSING ========================*/
2203
/*********************************************************************//**
2204
Checks if a table is referenced by foreign keys.
2205
@return TRUE if table is referenced by a foreign key */
2052
/*************************************************************************
2053
Checks if a table is referenced by foreign keys. */
2208
2056
dict_table_is_referenced_by_foreign_key(
2209
2057
/*====================================*/
2210
const dict_table_t* table) /*!< in: InnoDB table */
2058
/* out: TRUE if table is referenced
2060
const dict_table_t* table) /* in: InnoDB table */
2212
2062
return(UT_LIST_GET_LEN(table->referenced_list) > 0);
2215
/*********************************************************************//**
2065
/*************************************************************************
2216
2066
Check if the index is referenced by a foreign key, if TRUE return foreign
2218
@return pointer to foreign key struct if index is defined for foreign
2219
key, otherwise NULL */
2221
2069
dict_foreign_t*
2222
2070
dict_table_get_referenced_constraint(
2223
2071
/*=================================*/
2224
dict_table_t* table, /*!< in: InnoDB table */
2225
dict_index_t* index) /*!< in: InnoDB index */
2072
/* out: pointer to foreign key struct if index
2073
is defined for foreign key, otherwise NULL */
2074
dict_table_t* table, /* in: InnoDB table */
2075
dict_index_t* index) /* in: InnoDB index */
2227
2077
dict_foreign_t* foreign;
2354
/*********************************************************************//**
2205
/*************************************************************************
2355
2206
Tries to find an index whose first fields are the columns in the array,
2356
2207
in the same order and is not marked for deletion and is not the same
2358
@return matching index, NULL if not found */
2361
2211
dict_foreign_find_index(
2362
2212
/*====================*/
2363
dict_table_t* table, /*!< in: table */
2364
const char** columns,/*!< in: array of column names */
2365
ulint n_cols, /*!< in: number of columns */
2366
dict_index_t* types_idx, /*!< in: NULL or an index to whose types the
2213
/* out: matching index, NULL if not found */
2214
dict_table_t* table, /* in: table */
2215
const char** columns,/* in: array of column names */
2216
ulint n_cols, /* in: number of columns */
2217
dict_index_t* types_idx, /* in: NULL or an index to whose types the
2367
2218
column types must match */
2368
2219
ibool check_charsets,
2369
/*!< in: whether to check charsets.
2220
/* in: whether to check charsets.
2370
2221
only has an effect if types_idx != NULL */
2371
2222
ulint check_null)
2372
/*!< in: nonzero if none of the columns must
2223
/* in: nonzero if none of the columns must
2373
2224
be declared NOT NULL */
2375
2226
dict_index_t* index;
2460
2312
FALSE/* allow columns to be NULL */));
2463
/**********************************************************************//**
2315
/**************************************************************************
2464
2316
Returns an index object by matching on the name and column names and
2465
if more than one index matches return the index with the max id
2466
@return matching index, NULL if not found */
2317
if more than one index matches return the index with the max id */
2469
2320
dict_table_get_index_by_max_id(
2470
2321
/*===========================*/
2471
dict_table_t* table, /*!< in: table */
2472
const char* name, /*!< in: the index name to find */
2473
const char** columns,/*!< in: array of column names */
2474
ulint n_cols) /*!< in: number of columns */
2322
/* out: matching index, NULL if not found */
2323
dict_table_t* table, /* in: table */
2324
const char* name, /* in: the index name to find */
2325
const char** columns,/* in: array of column names */
2326
ulint n_cols) /* in: number of columns */
2476
2328
dict_index_t* index;
2477
2329
dict_index_t* found;
2554
2407
fputs("The index in the foreign key in table is ", file);
2555
2408
ut_print_name(file, NULL, FALSE, fk->foreign_index->name);
2557
"See " REFMAN "innodb-foreign-key-constraints.html\n"
2410
"See http://dev.mysql.com/doc/refman/5.1/en/"
2411
"innodb-foreign-key-constraints.html\n"
2558
2412
"for correct foreign key definition.\n",
2561
2415
mutex_exit(&dict_foreign_err_mutex);
2564
/**********************************************************************//**
2418
/**************************************************************************
2565
2419
Adds a foreign key constraint object to the dictionary cache. May free
2566
2420
the object if there already is an object with the same identifier in.
2567
2421
At least one of the foreign table and the referenced table must already
2568
be in the dictionary cache!
2569
@return DB_SUCCESS or error code */
2422
be in the dictionary cache! */
2572
2425
dict_foreign_add_to_cache(
2573
2426
/*======================*/
2574
dict_foreign_t* foreign, /*!< in, own: foreign key constraint */
2575
ibool check_charsets) /*!< in: TRUE=check charset
2427
/* out: DB_SUCCESS or error code */
2428
dict_foreign_t* foreign, /* in, own: foreign key constraint */
2429
ibool check_charsets) /* in: TRUE=check charset
2576
2430
compatibility */
2578
2432
dict_table_t* for_table;
2730
/*********************************************************************//**
2731
Accepts a specified string. Comparisons are case-insensitive.
2732
@return if string was accepted, the pointer is moved after that, else
2584
/*************************************************************************
2585
Accepts a specified string. Comparisons are case-insensitive. */
2738
const void* cs,/*!< in: the character set of ptr */
2739
const char* ptr, /*!< in: scan from this */
2740
const char* string, /*!< in: accept only this string as the next
2590
/* out: if string was accepted, the pointer
2591
is moved after that, else ptr is returned */
2592
struct charset_info_st* cs,/* in: the character set of ptr */
2593
const char* ptr, /* in: scan from this */
2594
const char* string, /* in: accept only this string as the next
2741
2595
non-whitespace string */
2742
ibool* success)/*!< out: TRUE if accepted */
2596
ibool* success)/* out: TRUE if accepted */
2744
2598
const char* old_ptr = ptr;
2745
2599
const char* old_ptr2;
2747
2601
*success = FALSE;
2749
while (innobase_isspace(cs, *ptr)) {
2603
while (my_isspace(cs, *ptr)) {
2763
2617
return(ptr + ut_strlen(string));
2766
/*********************************************************************//**
2620
/*************************************************************************
2767
2621
Scans an id. For the lexical definition of an 'id', see the code below.
2768
Strips backquotes or double quotes from around the id.
2769
@return scanned to */
2622
Strips backquotes or double quotes from around the id. */
2774
const void* cs,/*!< in: the character set of ptr */
2775
const char* ptr, /*!< in: scanned to */
2776
mem_heap_t* heap, /*!< in: heap where to allocate the id
2627
/* out: scanned to */
2628
struct charset_info_st* cs,/* in: the character set of ptr */
2629
const char* ptr, /* in: scanned to */
2630
mem_heap_t* heap, /* in: heap where to allocate the id
2777
2631
(NULL=id will not be allocated, but it
2778
2632
will point to string near ptr) */
2779
const char** id, /*!< out,own: the id; NULL if no id was
2633
const char** id, /* out,own: the id; NULL if no id was
2781
ibool table_id,/*!< in: TRUE=convert the allocated id
2635
ibool table_id,/* in: TRUE=convert the allocated id
2782
2636
as a table name; FALSE=convert to UTF-8 */
2783
2637
ibool accept_also_dot)
2784
/*!< in: TRUE if also a dot can appear in a
2638
/* in: TRUE if also a dot can appear in a
2785
2639
non-quoted id; in a quoted id it can appear
2861
2715
/* Convert the identifier from connection character set
2863
2717
len = 3 * len + 1;
2864
*id = dst = static_cast<char *>(mem_heap_alloc(heap, len));
2718
*id = dst = mem_heap_alloc(heap, len);
2866
2720
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())) {
2721
} else if (!strncmp(str, srv_mysql50_table_name_prefix,
2722
sizeof srv_mysql50_table_name_prefix)) {
2869
2723
/* This is a pre-5.1 table name
2870
2724
containing chars other than [A-Za-z0-9].
2871
2725
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();
2726
str += sizeof srv_mysql50_table_name_prefix;
2727
len -= sizeof srv_mysql50_table_name_prefix;
2874
2728
goto convert_id;
2876
2730
/* Encode using filename-safe characters. */
2877
2731
len = 5 * len + 1;
2878
*id = dst = static_cast<char *>(mem_heap_alloc(heap, len));
2732
*id = dst = mem_heap_alloc(heap, len);
2880
2734
innobase_convert_from_table_id(cs, dst, str, len);
2886
/*********************************************************************//**
2887
Tries to scan a column name.
2888
@return scanned to */
2740
/*************************************************************************
2741
Tries to scan a column name. */
2893
const void* cs, /*!< in: the character set of ptr */
2894
const char* ptr, /*!< in: scanned to */
2895
ibool* success,/*!< out: TRUE if success */
2896
dict_table_t* table, /*!< in: table in which the column is */
2897
const dict_col_t** column, /*!< out: pointer to column if success */
2898
mem_heap_t* heap, /*!< in: heap where to allocate */
2899
const char** name) /*!< out,own: the column name;
2746
/* out: scanned to */
2747
struct charset_info_st* cs, /* in: the character set of ptr */
2748
const char* ptr, /* in: scanned to */
2749
ibool* success,/* out: TRUE if success */
2750
dict_table_t* table, /* in: table in which the column is */
2751
const dict_col_t** column, /* out: pointer to column if success */
2752
mem_heap_t* heap, /* in: heap where to allocate */
2753
const char** name) /* out,own: the column name;
2900
2754
NULL if no name was scannable */
2937
/*********************************************************************//**
2938
Scans a table name from an SQL string.
2939
@return scanned to */
2791
/*************************************************************************
2792
Scans a table name from an SQL string. */
2942
2795
dict_scan_table_name(
2943
2796
/*=================*/
2944
const void* cs,/*!< in: the character set of ptr */
2945
const char* ptr, /*!< in: scanned to */
2946
dict_table_t** table, /*!< out: table object or NULL */
2947
const char* name, /*!< in: foreign key table name */
2948
ibool* success,/*!< out: TRUE if ok name found */
2949
mem_heap_t* heap, /*!< in: heap where to allocate the id */
2950
const char** ref_name)/*!< out,own: the table name;
2797
/* out: scanned to */
2798
struct charset_info_st* cs,/* in: the character set of ptr */
2799
const char* ptr, /* in: scanned to */
2800
dict_table_t** table, /* out: table object or NULL */
2801
const char* name, /* in: foreign key table name */
2802
ibool* success,/* out: TRUE if ok name found */
2803
mem_heap_t* heap, /* in: heap where to allocate the id */
2804
const char** ref_name)/* out,own: the table name;
2951
2805
NULL if no name was scannable */
2953
2807
const char* database_name = NULL;
3061
/*********************************************************************//**
2915
/*************************************************************************
3062
2916
Removes MySQL comments from an SQL string. A comment is either
3063
2917
(a) '#' to the end of the line,
3064
(b) '--[space]' to the end of the line, or
3065
(c) '[slash][asterisk]' till the next '[asterisk][slash]' (like the familiar
3067
@return own: SQL string stripped from comments; the caller must free
3068
this with mem_free()! */
2918
(b) '--<space>' to the end of the line, or
2919
(c) '<slash><asterisk>' till the next '<asterisk><slash>' (like the familiar
2920
C comment syntax). */
3071
2923
dict_strip_comments(
3072
2924
/*================*/
3073
const char* sql_string, /*!< in: SQL string */
3074
size_t sql_length) /*!< in: length of sql_string */
2925
/* out, own: SQL string stripped from
2926
comments; the caller must free this
2928
const char* sql_string) /* in: SQL string */
3077
2931
const char* sptr;
3078
const char* eptr = sql_string + sql_length;
3080
2933
/* unclosed quote character (0 if none) */
3081
2934
char quote = 0;
3083
str = static_cast<char *>(mem_alloc(sql_length + 1));
2936
str = mem_alloc(strlen(sql_string) + 1);
3085
2938
sptr = sql_string;
3090
if (sptr >= eptr || *sptr == '\0') {
2943
if (*sptr == '\0') {
3094
ut_a(ptr <= str + sql_length);
2946
ut_a(ptr <= str + strlen(sql_string));
3221
3069
mutex_exit(&dict_foreign_err_mutex);
3224
/*********************************************************************//**
3072
/*************************************************************************
3225
3073
Scans a table create SQL string and adds to the data dictionary the foreign
3226
3074
key constraints declared in the string. This function should be called after
3227
3075
the indexes for a table have been created. Each foreign key constraint must
3228
3076
be accompanied with indexes in both participating tables. The indexes are
3229
allowed to contain more fields than mentioned in the constraint.
3230
@return error code or DB_SUCCESS */
3077
allowed to contain more fields than mentioned in the constraint. */
3233
3080
dict_create_foreign_constraints_low(
3234
3081
/*================================*/
3235
trx_t* trx, /*!< in: transaction */
3236
mem_heap_t* heap, /*!< in: memory heap */
3237
const void* cs,/*!< in: the character set of sql_string */
3082
/* out: error code or DB_SUCCESS */
3083
trx_t* trx, /* in: transaction */
3084
mem_heap_t* heap, /* in: memory heap */
3085
struct charset_info_st* cs,/* in: the character set of sql_string */
3238
3086
const char* sql_string,
3239
/*!< in: CREATE TABLE or ALTER TABLE statement
3087
/* in: CREATE TABLE or ALTER TABLE statement
3240
3088
where foreign keys are declared like:
3241
3089
FOREIGN KEY (a, b) REFERENCES table2(c, d),
3242
3090
table2 can be written also with the database
3243
3091
name before it: test.table2; the default
3244
3092
database is the database of parameter name */
3245
const char* name, /*!< in: table full name in the normalized form
3093
const char* name, /* in: table full name in the normalized form
3246
3094
database_name/table_name */
3247
3095
ibool reject_fks)
3248
/*!< in: if TRUE, fail with error code
3096
/* in: if TRUE, fail with error code
3249
3097
DB_CANNOT_ADD_CONSTRAINT if any foreign
3250
3098
keys are found. */
3802
/*********************************************************************//**
3651
/*************************************************************************
3803
3652
Scans a table create SQL string and adds to the data dictionary the foreign
3804
3653
key constraints declared in the string. This function should be called after
3805
3654
the indexes for a table have been created. Each foreign key constraint must
3806
3655
be accompanied with indexes in both participating tables. The indexes are
3807
allowed to contain more fields than mentioned in the constraint.
3808
@return error code or DB_SUCCESS */
3656
allowed to contain more fields than mentioned in the constraint. */
3811
3659
dict_create_foreign_constraints(
3812
3660
/*============================*/
3813
trx_t* trx, /*!< in: transaction */
3814
const char* sql_string, /*!< in: table create statement where
3661
/* out: error code or DB_SUCCESS */
3662
trx_t* trx, /* in: transaction */
3663
const char* sql_string, /* in: table create statement where
3815
3664
foreign keys are declared like:
3816
3665
FOREIGN KEY (a, b) REFERENCES
3817
3666
table2(c, d), table2 can be written
3850
/**********************************************************************//**
3851
Parses the CONSTRAINT id's to be dropped in an ALTER TABLE statement.
3852
@return DB_SUCCESS or DB_CANNOT_DROP_CONSTRAINT if syntax error or the
3853
constraint id does not match */
3698
/**************************************************************************
3699
Parses the CONSTRAINT id's to be dropped in an ALTER TABLE statement. */
3856
3702
dict_foreign_parse_drop_constraints(
3857
3703
/*================================*/
3858
mem_heap_t* heap, /*!< in: heap from which we can
3704
/* out: DB_SUCCESS or
3705
DB_CANNOT_DROP_CONSTRAINT if
3706
syntax error or the constraint
3707
id does not match */
3708
mem_heap_t* heap, /* in: heap from which we can
3859
3709
allocate memory */
3860
trx_t* trx, /*!< in: transaction */
3861
dict_table_t* table, /*!< in: table */
3862
ulint* n, /*!< out: number of constraints
3710
trx_t* trx, /* in: transaction */
3711
dict_table_t* table, /* in: table */
3712
ulint* n, /* out: number of constraints
3864
const char*** constraints_to_drop) /*!< out: id's of the
3714
const char*** constraints_to_drop) /* out: id's of the
3865
3715
constraints to drop */
3867
3717
dict_foreign_t* foreign;
3871
3720
const char* ptr;
3872
3721
const char* id;
3873
3722
FILE* ef = dict_foreign_err_file;
3723
struct charset_info_st* cs;
3877
3726
ut_a(trx->mysql_thd);
3879
cs = trx->session()->charset();
3728
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);
3732
*constraints_to_drop = mem_heap_alloc(heap, 1000 * sizeof(char*));
3734
str = dict_strip_comments(*(trx->mysql_query_str));
3891
3737
ut_ad(mutex_own(&(dict_sys->mutex)));
4047
3894
#endif /* UNIV_DEBUG */
4049
/**********************************************************************//**
4050
Builds a node pointer out of a physical record and a page number.
4051
@return own: node pointer */
3896
/**************************************************************************
3897
Builds a node pointer out of a physical record and a page number. */
4054
3900
dict_index_build_node_ptr(
4055
3901
/*======================*/
4056
const dict_index_t* index, /*!< in: index */
4057
const rec_t* rec, /*!< in: record for which to build node
4059
ulint page_no,/*!< in: page number to put in node
4061
mem_heap_t* heap, /*!< in: memory heap where pointer
3902
/* out, own: node pointer */
3903
const dict_index_t* index, /* in: index */
3904
const rec_t* rec, /* in: record for which to build node
3906
ulint page_no,/* in: page number to put in node
3908
mem_heap_t* heap, /* in: memory heap where pointer
4063
ulint level) /*!< in: level of rec in tree:
3910
ulint level) /* in: level of rec in tree:
4064
3911
0 means leaf level */
4066
3913
dtuple_t* tuple;
4118
/**********************************************************************//**
3965
/**************************************************************************
4119
3966
Copies an initial segment of a physical record, long enough to specify an
4120
index entry uniquely.
4121
@return pointer to the prefix record */
3967
index entry uniquely. */
4124
3970
dict_index_copy_rec_order_prefix(
4125
3971
/*=============================*/
4126
const dict_index_t* index, /*!< in: index */
4127
const rec_t* rec, /*!< in: record for which to
3972
/* out: pointer to the prefix record */
3973
const dict_index_t* index, /* in: index */
3974
const rec_t* rec, /* in: record for which to
4129
ulint* n_fields,/*!< out: number of fields copied */
4130
byte** buf, /*!< in/out: memory buffer for the
3976
ulint* n_fields,/* out: number of fields copied */
3977
byte** buf, /* in/out: memory buffer for the
4131
3978
copied prefix, or NULL */
4132
ulint* buf_size)/*!< in/out: buffer size */
3979
ulint* buf_size)/* in/out: buffer size */
4146
3993
return(rec_copy_prefix_to_buf(rec, index, n, buf, buf_size));
4149
/**********************************************************************//**
4150
Builds a typed data tuple out of a physical record.
4151
@return own: data tuple */
3996
/**************************************************************************
3997
Builds a typed data tuple out of a physical record. */
4154
4000
dict_index_build_data_tuple(
4155
4001
/*========================*/
4156
dict_index_t* index, /*!< in: index tree */
4157
rec_t* rec, /*!< in: record for which to build data tuple */
4158
ulint n_fields,/*!< in: number of data fields */
4159
mem_heap_t* heap) /*!< in: memory heap where tuple created */
4002
/* out, own: data tuple */
4003
dict_index_t* index, /* in: index tree */
4004
rec_t* rec, /* in: record for which to build data tuple */
4005
ulint n_fields,/* in: number of data fields */
4006
mem_heap_t* heap) /* in: memory heap where tuple created */
4161
4008
dtuple_t* tuple;
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;
4123
size = btr_get_size(index, BTR_TOTAL_SIZE);
4125
index->stat_index_size = size;
4127
sum_of_index_sizes += size;
4129
size = btr_get_size(index, BTR_N_LEAF_PAGES);
4132
/* The root node of the tree is a leaf */
4136
index->stat_n_leaf_pages = size;
4138
btr_estimate_number_of_different_key_vals(index);
4313
4140
index = dict_table_get_next_index(index);
4316
4143
index = dict_table_get_first_index(table);
4408
4245
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);
4247
dict_update_statistics_low(table, TRUE);
4414
4249
fprintf(stderr,
4415
4250
"--------------------------------------\n"
4416
"TABLE: name %s, id %llu, flags %lx, columns %lu,"
4251
"TABLE: name %s, id %lu %lu, flags %lx, columns %lu,"
4417
4252
" indexes %lu, appr.rows %lu\n"
4255
(ulong) ut_dulint_get_high(table->id),
4256
(ulong) ut_dulint_get_low(table->id),
4421
4257
(ulong) table->flags,
4422
4258
(ulong) table->n_cols,
4423
4259
(ulong) UT_LIST_GET_LEN(table->indexes),
4424
4260
(ulong) table->stat_n_rows);
4426
for (i = 0; i < (ulint) table->n_cols; i++) {
4262
for (i = 0; i + 1 < (ulint) table->n_cols; i++) {
4427
4263
dict_col_print_low(table, dict_table_get_nth_col(table, i));
4428
4264
fputs("; ", stderr);
4729
4573
mutex_exit(&(dict_sys->mutex));
4732
/********************************************************************//**
4576
/************************************************************************
4733
4577
Displays the names of the index and the table. */
4736
4580
dict_index_name_print(
4737
4581
/*==================*/
4738
FILE* file, /*!< in: output stream */
4739
trx_t* trx, /*!< in: transaction */
4740
const dict_index_t* index) /*!< in: index to print */
4582
FILE* file, /* in: output stream */
4583
trx_t* trx, /* in: transaction */
4584
const dict_index_t* index) /* in: index to print */
4742
4586
fputs("index ", file);
4743
4587
ut_print_name(file, trx, FALSE, index->name);
4744
4588
fputs(" of table ", file);
4745
4589
ut_print_name(file, trx, TRUE, index->table_name);
4747
#endif /* !UNIV_HOTBACKUP */
4749
/**********************************************************************//**
4750
Inits dict_ind_redundant and dict_ind_compact. */
4756
dict_table_t* table;
4758
/* create dummy table and index for REDUNDANT infimum and supremum */
4759
table = dict_mem_table_create("SYS_DUMMY1", DICT_HDR_SPACE, 1, 0);
4760
dict_mem_table_add_col(table, NULL, NULL, DATA_CHAR,
4761
DATA_ENGLISH | DATA_NOT_NULL, 8);
4763
dict_ind_redundant = dict_mem_index_create("SYS_DUMMY1", "SYS_DUMMY1",
4764
DICT_HDR_SPACE, 0, 1);
4765
dict_index_add_col(dict_ind_redundant, table,
4766
dict_table_get_nth_col(table, 0), 0);
4767
dict_ind_redundant->table = table;
4768
/* create dummy table and index for COMPACT infimum and supremum */
4769
table = dict_mem_table_create("SYS_DUMMY2",
4770
DICT_HDR_SPACE, 1, DICT_TF_COMPACT);
4771
dict_mem_table_add_col(table, NULL, NULL, DATA_CHAR,
4772
DATA_ENGLISH | DATA_NOT_NULL, 8);
4773
dict_ind_compact = dict_mem_index_create("SYS_DUMMY2", "SYS_DUMMY2",
4774
DICT_HDR_SPACE, 0, 1);
4775
dict_index_add_col(dict_ind_compact, table,
4776
dict_table_get_nth_col(table, 0), 0);
4777
dict_ind_compact->table = table;
4779
/* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */
4780
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
#ifndef UNIV_HOTBACKUP
4804
/**********************************************************************//**
4806
@return index, NULL if does not exist */
4592
/**************************************************************************
4593
Get index by name */
4809
4596
dict_table_get_index_on_name(
4810
4597
/*=========================*/
4811
dict_table_t* table, /*!< in: table */
4812
const char* name) /*!< in: name of the index to find */
4598
/* out: index, NULL if does not exist */
4599
dict_table_t* table, /* in: table */
4600
const char* name) /* in: name of the index to find */
4814
4602
dict_index_t* index;
4848
4635
if (foreign->foreign_index == index) {
4849
4636
dict_index_t* new_index
4850
4637
= 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
4640
foreign->foreign_index = new_index;
4864
/**********************************************************************//**
4645
/**************************************************************************
4865
4646
In case there is more than one index with the same name return the index
4867
@return index, NULL if does not exist */
4647
with the min(id). */
4870
4650
dict_table_get_index_on_name_and_min_id(
4871
4651
/*=====================================*/
4872
dict_table_t* table, /*!< in: table */
4873
const char* name) /*!< in: name of the index to find */
4652
/* out: index, NULL if does not exist */
4653
dict_table_t* table, /* in: table */
4654
const char* name) /* in: name of the index to find */
4875
4656
dict_index_t* index;
4876
4657
dict_index_t* min_index; /* Index with matching name and min(id) */
4935
4711
index1 = UT_LIST_GET_NEXT(indexes, index1);
4712
index2 = UT_LIST_GET_NEXT(indexes, index1);
4938
4715
#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
#endif /* !UNIV_HOTBACKUP */