1 /*****************************************************************************
3 Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
5 This program is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free Software
7 Foundation; version 2 of the License.
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
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.,
15 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
17 *****************************************************************************/
19 /******************************************************************//**
20 @file include/dict0dict.ic
21 Data dictionary system
23 Created 1/8/1996 Heikki Tuuri
24 ***********************************************************************/
26 #include "data0type.h"
27 #ifndef UNIV_HOTBACKUP
28 #include "dict0load.h"
29 #include "rem0types.h"
31 /*********************************************************************//**
32 Gets the column data type. */
37 const dict_col_t* col, /*!< in: column */
38 dtype_t* type) /*!< out: data type */
42 type->mtype = col->mtype;
43 type->prtype = col->prtype;
45 type->mbminlen = col->mbminlen;
46 type->mbmaxlen = col->mbmaxlen;
48 #endif /* !UNIV_HOTBACKUP */
51 /*********************************************************************//**
52 Assert that a column and a data type match.
56 dict_col_type_assert_equal(
57 /*=======================*/
58 const dict_col_t* col, /*!< in: column */
59 const dtype_t* type) /*!< in: data type */
64 ut_ad(col->mtype == type->mtype);
65 ut_ad(col->prtype == type->prtype);
66 ut_ad(col->len == type->len);
67 # ifndef UNIV_HOTBACKUP
68 ut_ad(col->mbminlen == type->mbminlen);
69 ut_ad(col->mbmaxlen == type->mbmaxlen);
70 # endif /* !UNIV_HOTBACKUP */
74 #endif /* UNIV_DEBUG */
76 #ifndef UNIV_HOTBACKUP
77 /***********************************************************************//**
78 Returns the minimum size of the column.
79 @return minimum size */
82 dict_col_get_min_size(
83 /*==================*/
84 const dict_col_t* col) /*!< in: column */
86 return(dtype_get_min_size_low(col->mtype, col->prtype, col->len,
87 col->mbminlen, col->mbmaxlen));
89 /***********************************************************************//**
90 Returns the maximum size of the column.
91 @return maximum size */
94 dict_col_get_max_size(
95 /*==================*/
96 const dict_col_t* col) /*!< in: column */
98 return(dtype_get_max_size_low(col->mtype, col->len));
100 #endif /* !UNIV_HOTBACKUP */
101 /***********************************************************************//**
102 Returns the size of a fixed size column, 0 if not a fixed size column.
103 @return fixed size, or 0 */
106 dict_col_get_fixed_size(
107 /*====================*/
108 const dict_col_t* col, /*!< in: column */
109 ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */
111 return(dtype_get_fixed_size_low(col->mtype, col->prtype, col->len,
112 col->mbminlen, col->mbmaxlen, comp));
114 /***********************************************************************//**
115 Returns the ROW_FORMAT=REDUNDANT stored SQL NULL size of a column.
116 For fixed length types it is the fixed length of the type, otherwise 0.
117 @return SQL null storage size in ROW_FORMAT=REDUNDANT */
120 dict_col_get_sql_null_size(
121 /*=======================*/
122 const dict_col_t* col, /*!< in: column */
123 ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */
125 return(dict_col_get_fixed_size(col, comp));
128 /*********************************************************************//**
129 Gets the column number.
130 @return col->ind, table column position (starting from 0) */
135 const dict_col_t* col) /*!< in: column */
142 /*********************************************************************//**
143 Gets the column position in the clustered index. */
146 dict_col_get_clust_pos(
147 /*===================*/
148 const dict_col_t* col, /*!< in: table column */
149 const dict_index_t* clust_index) /*!< in: clustered index */
155 ut_ad(dict_index_is_clust(clust_index));
157 for (i = 0; i < clust_index->n_def; i++) {
158 const dict_field_t* field = &clust_index->fields[i];
160 if (!field->prefix_len && field->col == col) {
165 return(ULINT_UNDEFINED);
168 #ifndef UNIV_HOTBACKUP
170 /********************************************************************//**
171 Gets the first index on the table (the clustered index).
172 @return index, NULL if none exists */
175 dict_table_get_first_index(
176 /*=======================*/
177 const dict_table_t* table) /*!< in: table */
180 ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
182 return(UT_LIST_GET_FIRST(((dict_table_t*) table)->indexes));
185 /********************************************************************//**
186 Gets the next index on the table.
187 @return index, NULL if none left */
190 dict_table_get_next_index(
191 /*======================*/
192 const dict_index_t* index) /*!< in: index */
195 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
197 return(UT_LIST_GET_NEXT(indexes, (dict_index_t*) index));
199 #endif /* UNIV_DEBUG */
200 #endif /* !UNIV_HOTBACKUP */
202 /********************************************************************//**
203 Check whether the index is the clustered index.
204 @return nonzero for clustered index, zero for other indexes */
209 const dict_index_t* index) /*!< in: index */
212 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
214 return(UNIV_UNLIKELY(index->type & DICT_CLUSTERED));
216 /********************************************************************//**
217 Check whether the index is unique.
218 @return nonzero for unique index, zero for other indexes */
221 dict_index_is_unique(
222 /*=================*/
223 const dict_index_t* index) /*!< in: index */
226 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
228 return(UNIV_UNLIKELY(index->type & DICT_UNIQUE));
231 /********************************************************************//**
232 Check whether the index is the insert buffer tree.
233 @return nonzero for insert buffer, zero for other indexes */
238 const dict_index_t* index) /*!< in: index */
241 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
243 return(UNIV_UNLIKELY(index->type & DICT_IBUF));
246 /********************************************************************//**
247 Check whether the index is a secondary index or the insert buffer tree.
248 @return nonzero for insert buffer, zero for other indexes */
251 dict_index_is_sec_or_ibuf(
252 /*======================*/
253 const dict_index_t* index) /*!< in: index */
258 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
262 return(UNIV_LIKELY(!(type & DICT_CLUSTERED) || (type & DICT_IBUF)));
265 /********************************************************************//**
266 Gets the number of user-defined columns in a table in the dictionary
268 @return number of user-defined (e.g., not ROW_ID) columns of a table */
271 dict_table_get_n_user_cols(
272 /*=======================*/
273 const dict_table_t* table) /*!< in: table */
276 ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
278 return(table->n_cols - DATA_N_SYS_COLS);
281 /********************************************************************//**
282 Gets the number of system columns in a table in the dictionary cache.
283 @return number of system (e.g., ROW_ID) columns of a table */
286 dict_table_get_n_sys_cols(
287 /*======================*/
288 const dict_table_t* table __attribute__((unused))) /*!< in: table */
291 ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
292 ut_ad(table->cached);
294 return(DATA_N_SYS_COLS);
297 /********************************************************************//**
298 Gets the number of all columns (also system) in a table in the dictionary
300 @return number of columns of a table */
303 dict_table_get_n_cols(
304 /*==================*/
305 const dict_table_t* table) /*!< in: table */
308 ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
310 return(table->n_cols);
314 /********************************************************************//**
315 Gets the nth column of a table.
316 @return pointer to column object */
319 dict_table_get_nth_col(
320 /*===================*/
321 const dict_table_t* table, /*!< in: table */
322 ulint pos) /*!< in: position of column */
325 ut_ad(pos < table->n_def);
326 ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
328 return((dict_col_t*) (table->cols) + pos);
331 /********************************************************************//**
332 Gets the given system column of a table.
333 @return pointer to column object */
336 dict_table_get_sys_col(
337 /*===================*/
338 const dict_table_t* table, /*!< in: table */
339 ulint sys) /*!< in: DATA_ROW_ID, ... */
344 ut_ad(sys < DATA_N_SYS_COLS);
345 ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
347 col = dict_table_get_nth_col(table, table->n_cols
348 - DATA_N_SYS_COLS + sys);
349 ut_ad(col->mtype == DATA_SYS);
350 ut_ad(col->prtype == (sys | DATA_NOT_NULL));
354 #endif /* UNIV_DEBUG */
356 /********************************************************************//**
357 Gets the given system column number of a table.
358 @return column number */
361 dict_table_get_sys_col_no(
362 /*======================*/
363 const dict_table_t* table, /*!< in: table */
364 ulint sys) /*!< in: DATA_ROW_ID, ... */
367 ut_ad(sys < DATA_N_SYS_COLS);
368 ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
370 return(table->n_cols - DATA_N_SYS_COLS + sys);
373 /********************************************************************//**
374 Check whether the table uses the compact page format.
375 @return TRUE if table uses the compact page format */
380 const dict_table_t* table) /*!< in: table */
384 #if DICT_TF_COMPACT != TRUE
388 return(UNIV_LIKELY(table->flags & DICT_TF_COMPACT));
391 /********************************************************************//**
392 Determine the file format of a table.
393 @return file format version */
396 dict_table_get_format(
397 /*==================*/
398 const dict_table_t* table) /*!< in: table */
402 return((table->flags & DICT_TF_FORMAT_MASK) >> DICT_TF_FORMAT_SHIFT);
405 /********************************************************************//**
406 Determine the file format of a table. */
409 dict_table_set_format(
410 /*==================*/
411 dict_table_t* table, /*!< in/out: table */
412 ulint format) /*!< in: file format version */
416 table->flags = (table->flags & ~DICT_TF_FORMAT_MASK)
417 | (format << DICT_TF_FORMAT_SHIFT);
420 /********************************************************************//**
421 Extract the compressed page size from table flags.
422 @return compressed page size, or 0 if not compressed */
425 dict_table_flags_to_zip_size(
426 /*=========================*/
427 ulint flags) /*!< in: flags */
429 ulint zip_size = flags & DICT_TF_ZSSIZE_MASK;
431 if (UNIV_UNLIKELY(zip_size)) {
432 zip_size = ((PAGE_ZIP_MIN_SIZE >> 1)
433 << (zip_size >> DICT_TF_ZSSIZE_SHIFT));
435 ut_ad(zip_size <= UNIV_PAGE_SIZE);
441 /********************************************************************//**
442 Check whether the table uses the compressed compact page format.
443 @return compressed page size, or 0 if not compressed */
448 const dict_table_t* table) /*!< in: table */
452 return(dict_table_flags_to_zip_size(table->flags));
455 /*********************************************************************//**
456 Obtain exclusive locks on all index trees of the table. This is to prevent
457 accessing index trees while InnoDB is updating internal metadata for
458 operations such as truncate tables. */
461 dict_table_x_lock_indexes(
462 /*======================*/
463 dict_table_t* table) /*!< in: table */
468 ut_ad(mutex_own(&(dict_sys->mutex)));
470 /* Loop through each index of the table and lock them */
471 for (index = dict_table_get_first_index(table);
473 index = dict_table_get_next_index(index)) {
474 rw_lock_x_lock(dict_index_get_lock(index));
478 /*********************************************************************//**
479 Release the exclusive locks on all index tree. */
482 dict_table_x_unlock_indexes(
483 /*========================*/
484 dict_table_t* table) /*!< in: table */
489 ut_ad(mutex_own(&(dict_sys->mutex)));
491 for (index = dict_table_get_first_index(table);
493 index = dict_table_get_next_index(index)) {
494 rw_lock_x_unlock(dict_index_get_lock(index));
497 /********************************************************************//**
498 Gets the number of fields in the internal representation of an index,
499 including fields added by the dictionary system.
500 @return number of fields */
503 dict_index_get_n_fields(
504 /*====================*/
505 const dict_index_t* index) /*!< in: an internal
506 representation of index (in
507 the dictionary cache) */
510 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
512 return(index->n_fields);
515 /********************************************************************//**
516 Gets the number of fields in the internal representation of an index
517 that uniquely determine the position of an index entry in the index, if
518 we do not take multiversioning into account: in the B-tree use the value
519 returned by dict_index_get_n_unique_in_tree.
520 @return number of fields */
523 dict_index_get_n_unique(
524 /*====================*/
525 const dict_index_t* index) /*!< in: an internal representation
526 of index (in the dictionary cache) */
529 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
530 ut_ad(index->cached);
532 return(index->n_uniq);
535 /********************************************************************//**
536 Gets the number of fields in the internal representation of an index
537 which uniquely determine the position of an index entry in the index, if
538 we also take multiversioning into account.
539 @return number of fields */
542 dict_index_get_n_unique_in_tree(
543 /*============================*/
544 const dict_index_t* index) /*!< in: an internal representation
545 of index (in the dictionary cache) */
548 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
549 ut_ad(index->cached);
551 if (dict_index_is_clust(index)) {
553 return(dict_index_get_n_unique(index));
556 return(dict_index_get_n_fields(index));
559 /********************************************************************//**
560 Gets the number of user-defined ordering fields in the index. In the internal
561 representation of clustered indexes we add the row id to the ordering fields
562 to make a clustered index unique, but this function returns the number of
563 fields the user defined in the index as ordering fields.
564 @return number of fields */
567 dict_index_get_n_ordering_defined_by_user(
568 /*======================================*/
569 const dict_index_t* index) /*!< in: an internal representation
570 of index (in the dictionary cache) */
572 return(index->n_user_defined_cols);
576 /********************************************************************//**
577 Gets the nth field of an index.
578 @return pointer to field object */
581 dict_index_get_nth_field(
582 /*=====================*/
583 const dict_index_t* index, /*!< in: index */
584 ulint pos) /*!< in: position of field */
587 ut_ad(pos < index->n_def);
588 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
590 return((dict_field_t*) (index->fields) + pos);
592 #endif /* UNIV_DEBUG */
594 /********************************************************************//**
595 Returns the position of a system column in an index.
596 @return position, ULINT_UNDEFINED if not contained */
599 dict_index_get_sys_col_pos(
600 /*=======================*/
601 const dict_index_t* index, /*!< in: index */
602 ulint type) /*!< in: DATA_ROW_ID, ... */
605 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
606 ut_ad(!(index->type & DICT_UNIVERSAL));
608 if (dict_index_is_clust(index)) {
610 return(dict_col_get_clust_pos(
611 dict_table_get_sys_col(index->table, type),
615 return(dict_index_get_nth_col_pos(
616 index, dict_table_get_sys_col_no(index->table, type)));
619 /*********************************************************************//**
620 Gets the field column.
621 @return field->col, pointer to the table column */
626 const dict_field_t* field) /*!< in: index field */
633 /********************************************************************//**
634 Gets pointer to the nth column in an index.
638 dict_index_get_nth_col(
639 /*===================*/
640 const dict_index_t* index, /*!< in: index */
641 ulint pos) /*!< in: position of the field */
643 return(dict_field_get_col(dict_index_get_nth_field(index, pos)));
646 /********************************************************************//**
647 Gets the column number the nth field in an index.
648 @return column number */
651 dict_index_get_nth_col_no(
652 /*======================*/
653 const dict_index_t* index, /*!< in: index */
654 ulint pos) /*!< in: position of the field */
656 return(dict_col_get_no(dict_index_get_nth_col(index, pos)));
659 #ifndef UNIV_HOTBACKUP
660 /********************************************************************//**
661 Returns the minimum data size of an index record.
662 @return minimum data size in bytes */
665 dict_index_get_min_size(
666 /*====================*/
667 const dict_index_t* index) /*!< in: index */
669 ulint n = dict_index_get_n_fields(index);
673 size += dict_col_get_min_size(dict_index_get_nth_col(index,
680 /*********************************************************************//**
681 Gets the space id of the root of the index tree.
685 dict_index_get_space(
686 /*=================*/
687 const dict_index_t* index) /*!< in: index */
690 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
692 return(index->space);
695 /*********************************************************************//**
696 Sets the space id of the root of the index tree. */
699 dict_index_set_space(
700 /*=================*/
701 dict_index_t* index, /*!< in/out: index */
702 ulint space) /*!< in: space id */
705 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
707 index->space = space;
710 /*********************************************************************//**
711 Gets the page number of the root of the index tree.
712 @return page number */
717 const dict_index_t* index) /*!< in: index */
720 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
725 /*********************************************************************//**
726 Gets the read-write lock of the index tree.
727 @return read-write lock */
732 dict_index_t* index) /*!< in: index */
735 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
737 return(&(index->lock));
740 /********************************************************************//**
741 Returns free space reserved for future updates of records. This is
742 relevant only in the case of many consecutive inserts, as updates
743 which make the records bigger might fragment the index.
744 @return number of free bytes on page, reserved for updates */
747 dict_index_get_space_reserve(void)
748 /*==============================*/
750 return(UNIV_PAGE_SIZE / 16);
753 /**********************************************************************//**
754 Checks if a table is in the dictionary cache.
755 @return table, NULL if not found */
758 dict_table_check_if_in_cache_low(
759 /*=============================*/
760 const char* table_name) /*!< in: table name */
766 ut_ad(mutex_own(&(dict_sys->mutex)));
768 /* Look for the table name in the hash table */
769 table_fold = ut_fold_string(table_name);
771 HASH_SEARCH(name_hash, dict_sys->table_hash, table_fold,
772 dict_table_t*, table, ut_ad(table->cached),
773 !strcmp(table->name, table_name));
777 /**********************************************************************//**
778 Gets a table; loads it to the dictionary cache if necessary. A low-level
780 @return table, NULL if not found */
785 const char* table_name) /*!< in: table name */
790 ut_ad(mutex_own(&(dict_sys->mutex)));
792 table = dict_table_check_if_in_cache_low(table_name);
795 table = dict_load_table(table_name);
798 ut_ad(!table || table->cached);
803 /**********************************************************************//**
804 Returns a table object based on table id.
805 @return table, NULL if does not exist */
808 dict_table_get_on_id_low(
809 /*=====================*/
810 dulint table_id) /*!< in: table id */
815 ut_ad(mutex_own(&(dict_sys->mutex)));
817 /* Look for the table name in the hash table */
818 fold = ut_fold_dulint(table_id);
820 HASH_SEARCH(id_hash, dict_sys->table_id_hash, fold,
821 dict_table_t*, table, ut_ad(table->cached),
822 !ut_dulint_cmp(table->id, table_id));
824 table = dict_load_table_on_id(table_id);
827 ut_ad(!table || table->cached);
829 /* TODO: should get the type information from MySQL */
833 #endif /* !UNIV_HOTBACKUP */