1 /**********************************************************************
6 Created 1/8/1996 Heikki Tuuri
7 ***********************************************************************/
12 #include "rem0types.h"
13 #include "data0type.h"
15 /*************************************************************************
16 Gets the column data type. */
21 const dict_col_t* col, /* in: column */
22 dtype_t* type) /* out: data type */
26 type->mtype = col->mtype;
27 type->prtype = col->prtype;
29 type->mbminlen = col->mbminlen;
30 type->mbmaxlen = col->mbmaxlen;
34 /*************************************************************************
35 Assert that a column and a data type match. */
38 dict_col_type_assert_equal(
39 /*=======================*/
41 const dict_col_t* col, /* in: column */
42 const dtype_t* type) /* in: data type */
47 ut_ad(col->mtype == type->mtype);
48 ut_ad(col->prtype == type->prtype);
49 ut_ad(col->len == type->len);
50 ut_ad(col->mbminlen == type->mbminlen);
51 ut_ad(col->mbmaxlen == type->mbmaxlen);
55 #endif /* UNIV_DEBUG */
57 /***************************************************************************
58 Returns the minimum size of the column. */
61 dict_col_get_min_size(
62 /*==================*/
63 /* out: minimum size */
64 const dict_col_t* col) /* in: column */
66 return(dtype_get_min_size_low(col->mtype, col->prtype, col->len,
67 col->mbminlen, col->mbmaxlen));
69 /***************************************************************************
70 Returns the maximum size of the column. */
73 dict_col_get_max_size(
74 /*==================*/
75 /* out: maximum size */
76 const dict_col_t* col) /* in: column */
78 return(dtype_get_max_size_low(col->mtype, col->len));
80 /***************************************************************************
81 Returns the size of a fixed size column, 0 if not a fixed size column. */
84 dict_col_get_fixed_size(
85 /*====================*/
86 /* out: fixed size, or 0 */
87 const dict_col_t* col) /* in: column */
89 return(dtype_get_fixed_size_low(col->mtype, col->prtype, col->len,
90 col->mbminlen, col->mbmaxlen));
92 /***************************************************************************
93 Returns the ROW_FORMAT=REDUNDANT stored SQL NULL size of a column.
94 For fixed length types it is the fixed length of the type, otherwise 0. */
97 dict_col_get_sql_null_size(
98 /*=======================*/
99 /* out: SQL null storage size
100 in ROW_FORMAT=REDUNDANT */
101 const dict_col_t* col) /* in: column */
103 return(dict_col_get_fixed_size(col));
106 /*************************************************************************
107 Gets the column number. */
112 const dict_col_t* col)
119 /*************************************************************************
120 Gets the column position in the clustered index. */
123 dict_col_get_clust_pos(
124 /*===================*/
125 const dict_col_t* col, /* in: table column */
126 const dict_index_t* clust_index) /* in: clustered index */
131 ut_ad(clust_index && clust_index->type & DICT_CLUSTERED);
133 for (i = 0; i < clust_index->n_def; i++) {
134 const dict_field_t* field = &clust_index->fields[i];
136 if (!field->prefix_len && field->col == col) {
141 return(ULINT_UNDEFINED);
144 /************************************************************************
145 Gets the first index on the table (the clustered index). */
148 dict_table_get_first_index(
149 /*=======================*/
150 /* out: index, NULL if none exists */
151 dict_table_t* table) /* in: table */
154 ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
156 return(UT_LIST_GET_FIRST(table->indexes));
159 /************************************************************************
160 Gets the next index on the table. */
163 dict_table_get_next_index(
164 /*======================*/
165 /* out: index, NULL if none left */
166 dict_index_t* index) /* in: index */
169 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
171 return(UT_LIST_GET_NEXT(indexes, index));
174 /************************************************************************
175 Gets the number of user-defined columns in a table in the dictionary
179 dict_table_get_n_user_cols(
180 /*=======================*/
181 /* out: number of user-defined (e.g., not
182 ROW_ID) columns of a table */
183 dict_table_t* table) /* in: table */
186 ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
188 return(table->n_cols - DATA_N_SYS_COLS);
191 /************************************************************************
192 Gets the number of system columns in a table in the dictionary cache. */
195 dict_table_get_n_sys_cols(
196 /*======================*/
197 /* out: number of system (e.g.,
198 ROW_ID) columns of a table */
199 dict_table_t* table __attribute__((unused))) /* in: table */
202 ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
203 ut_ad(table->cached);
205 return(DATA_N_SYS_COLS);
208 /************************************************************************
209 Gets the number of all columns (also system) in a table in the dictionary
213 dict_table_get_n_cols(
214 /*==================*/
215 /* out: number of columns of a table */
216 dict_table_t* table) /* in: table */
219 ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
221 return(table->n_cols);
224 /************************************************************************
225 Gets the nth column of a table. */
228 dict_table_get_nth_col(
229 /*===================*/
230 /* out: pointer to column object */
231 const dict_table_t* table, /* in: table */
232 ulint pos) /* in: position of column */
235 ut_ad(pos < table->n_def);
236 ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
238 return((table->cols) + pos);
241 /************************************************************************
242 Gets the given system column of a table. */
245 dict_table_get_sys_col(
246 /*===================*/
247 /* out: pointer to column object */
248 const dict_table_t* table, /* in: table */
249 ulint sys) /* in: DATA_ROW_ID, ... */
251 const dict_col_t* col;
254 ut_ad(sys < DATA_N_SYS_COLS);
255 ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
257 col = dict_table_get_nth_col(table, table->n_cols
258 - DATA_N_SYS_COLS + sys);
259 ut_ad(col->mtype == DATA_SYS);
260 ut_ad(col->prtype == (sys | DATA_NOT_NULL));
265 /************************************************************************
266 Gets the given system column number of a table. */
269 dict_table_get_sys_col_no(
270 /*======================*/
271 /* out: column number */
272 dict_table_t* table, /* in: table */
273 ulint sys) /* in: DATA_ROW_ID, ... */
276 ut_ad(sys < DATA_N_SYS_COLS);
277 ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
279 return(table->n_cols - DATA_N_SYS_COLS + sys);
282 /************************************************************************
283 Check whether the table uses the compact page format. */
288 /* out: TRUE if table uses the
289 compact page format */
290 const dict_table_t* table) /* in: table */
294 #if DICT_TF_COMPACT != TRUE
298 return(UNIV_LIKELY(table->flags & DICT_TF_COMPACT));
301 /*********************************************************************//**
302 Obtain exclusive locks on all index trees of the table. This is to prevent
303 accessing index trees while InnoDB is updating internal metadata for
304 operations such as truncate tables. */
307 dict_table_x_lock_indexes(
308 /*======================*/
309 dict_table_t* table) /* in: table */
314 ut_ad(mutex_own(&(dict_sys->mutex)));
316 /* Loop through each index of the table and lock them */
317 for (index = dict_table_get_first_index(table);
319 index = dict_table_get_next_index(index)) {
320 rw_lock_x_lock(dict_index_get_lock(index));
324 /*********************************************************************//**
325 Release the exclusive locks on all index tree. */
328 dict_table_x_unlock_indexes(
329 /*========================*/
330 dict_table_t* table) /* in: table */
335 ut_ad(mutex_own(&(dict_sys->mutex)));
337 for (index = dict_table_get_first_index(table);
339 index = dict_table_get_next_index(index)) {
340 rw_lock_x_unlock(dict_index_get_lock(index));
343 /************************************************************************
344 Gets the number of fields in the internal representation of an index,
345 including fields added by the dictionary system. */
348 dict_index_get_n_fields(
349 /*====================*/
350 /* out: number of fields */
351 dict_index_t* index) /* in: an internal representation of index
352 (in the dictionary cache) */
355 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
357 return(index->n_fields);
360 /************************************************************************
361 Gets the number of fields in the internal representation of an index
362 that uniquely determine the position of an index entry in the index, if
363 we do not take multiversioning into account: in the B-tree use the value
364 returned by dict_index_get_n_unique_in_tree. */
367 dict_index_get_n_unique(
368 /*====================*/
369 /* out: number of fields */
370 dict_index_t* index) /* in: an internal representation of index
371 (in the dictionary cache) */
374 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
375 ut_ad(index->cached);
377 return(index->n_uniq);
380 /************************************************************************
381 Gets the number of fields in the internal representation of an index
382 which uniquely determine the position of an index entry in the index, if
383 we also take multiversioning into account. */
386 dict_index_get_n_unique_in_tree(
387 /*============================*/
388 /* out: number of fields */
389 dict_index_t* index) /* in: an internal representation of index
390 (in the dictionary cache) */
393 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
394 ut_ad(index->cached);
396 if (index->type & DICT_CLUSTERED) {
398 return(dict_index_get_n_unique(index));
401 return(dict_index_get_n_fields(index));
404 /************************************************************************
405 Gets the number of user-defined ordering fields in the index. In the internal
406 representation of clustered indexes we add the row id to the ordering fields
407 to make a clustered index unique, but this function returns the number of
408 fields the user defined in the index as ordering fields. */
411 dict_index_get_n_ordering_defined_by_user(
412 /*======================================*/
413 /* out: number of fields */
414 dict_index_t* index) /* in: an internal representation of index
415 (in the dictionary cache) */
417 return(index->n_user_defined_cols);
420 /************************************************************************
421 Gets the nth field of an index. */
424 dict_index_get_nth_field(
425 /*=====================*/
426 /* out: pointer to field object */
427 dict_index_t* index, /* in: index */
428 ulint pos) /* in: position of field */
431 ut_ad(pos < index->n_def);
432 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
434 return((index->fields) + pos);
437 /************************************************************************
438 Returns the position of a system column in an index. */
441 dict_index_get_sys_col_pos(
442 /*=======================*/
443 /* out: position, ULINT_UNDEFINED if not
445 dict_index_t* index, /* in: index */
446 ulint type) /* in: DATA_ROW_ID, ... */
449 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
450 ut_ad(!(index->type & DICT_UNIVERSAL));
452 if (index->type & DICT_CLUSTERED) {
454 return(dict_col_get_clust_pos(
455 dict_table_get_sys_col(index->table, type),
459 return(dict_index_get_nth_col_pos(
460 index, dict_table_get_sys_col_no(index->table, type)));
463 /*************************************************************************
464 Gets the field column. */
469 const dict_field_t* field)
476 /************************************************************************
477 Gets pointer to the nth column in an index. */
480 dict_index_get_nth_col(
481 /*===================*/
483 const dict_index_t* index, /* in: index */
484 ulint pos) /* in: position of the field */
486 return(dict_field_get_col(dict_index_get_nth_field((dict_index_t*)
490 /************************************************************************
491 Gets the column number the nth field in an index. */
494 dict_index_get_nth_col_no(
495 /*======================*/
496 /* out: column number */
497 const dict_index_t* index, /* in: index */
498 ulint pos) /* in: position of the field */
500 return(dict_col_get_no(dict_index_get_nth_col(index, pos)));
503 /*************************************************************************
504 Gets the space id of the root of the index tree. */
507 dict_index_get_space(
508 /*=================*/
510 dict_index_t* index) /* in: index */
513 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
515 return(index->space);
518 /*************************************************************************
519 Sets the space id of the root of the index tree. */
522 dict_index_set_space(
523 /*=================*/
524 dict_index_t* index, /* in: index */
525 ulint space) /* in: space id */
528 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
530 index->space = space;
533 /*************************************************************************
534 Gets the page number of the root of the index tree. */
539 /* out: page number */
540 dict_index_t* index) /* in: index */
543 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
548 /*************************************************************************
549 Sets the page number of the root of index tree. */
554 dict_index_t* index, /* in: index */
555 ulint page) /* in: page number */
558 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
563 /*************************************************************************
564 Gets the type of the index tree. */
570 dict_index_t* index) /* in: index */
573 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
578 /*************************************************************************
579 Gets the read-write lock of the index tree. */
584 /* out: read-write lock */
585 dict_index_t* index) /* in: index */
588 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
590 return(&(index->lock));
593 /************************************************************************
594 Returns free space reserved for future updates of records. This is
595 relevant only in the case of many consecutive inserts, as updates
596 which make the records bigger might fragment the index. */
599 dict_index_get_space_reserve(void)
600 /*==============================*/
601 /* out: number of free bytes on page,
602 reserved for updates */
604 return(UNIV_PAGE_SIZE / 16);
607 /**************************************************************************
608 Checks if a table is in the dictionary cache. */
611 dict_table_check_if_in_cache_low(
612 /*=============================*/
613 /* out: table, NULL if not found */
614 const char* table_name) /* in: table name */
620 ut_ad(mutex_own(&(dict_sys->mutex)));
622 /* Look for the table name in the hash table */
623 table_fold = ut_fold_string(table_name);
625 HASH_SEARCH(name_hash, dict_sys->table_hash, table_fold, table,
626 ut_strcmp(table->name, table_name) == 0);
630 /**************************************************************************
631 Gets a table; loads it to the dictionary cache if necessary. A low-level
637 /* out: table, NULL if not found */
638 const char* table_name) /* in: table name */
643 ut_ad(mutex_own(&(dict_sys->mutex)));
645 table = dict_table_check_if_in_cache_low(table_name);
648 table = dict_load_table(table_name);
654 /**************************************************************************
655 Returns a table object based on table id. */
658 dict_table_get_on_id_low(
659 /*=====================*/
660 /* out: table, NULL if does not exist */
661 dulint table_id) /* in: table id */
666 ut_ad(mutex_own(&(dict_sys->mutex)));
668 /* Look for the table name in the hash table */
669 fold = ut_fold_dulint(table_id);
671 HASH_SEARCH(id_hash, dict_sys->table_id_hash, fold, table,
672 ut_dulint_cmp(table->id, table_id) == 0);
674 table = dict_load_table_on_id(table_id);
677 /* TODO: should get the type information from MySQL */
682 /**************************************************************************
683 Returns an index object. */
686 dict_table_get_index(
687 /*=================*/
688 /* out: index, NULL if does not exist */
689 dict_table_t* table, /* in: table */
690 const char* name) /* in: index name */
692 dict_index_t* index = NULL;
694 index = dict_table_get_first_index(table);
696 while (index != NULL) {
697 if (ut_strcmp(name, index->name) == 0) {
702 index = dict_table_get_next_index(index);