1
/*****************************************************************************
3
Copyright (c) 1996, 2009, Innobase Oy. 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., 59 Temple
15
Place, Suite 330, Boston, MA 02111-1307 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
Gets the number of fields in the internal representation of an index,
457
including fields added by the dictionary system.
458
@return number of fields */
461
dict_index_get_n_fields(
462
/*====================*/
463
const dict_index_t* index) /*!< in: an internal
464
representation of index (in
465
the dictionary cache) */
468
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
470
return(index->n_fields);
473
/********************************************************************//**
474
Gets the number of fields in the internal representation of an index
475
that uniquely determine the position of an index entry in the index, if
476
we do not take multiversioning into account: in the B-tree use the value
477
returned by dict_index_get_n_unique_in_tree.
478
@return number of fields */
481
dict_index_get_n_unique(
482
/*====================*/
483
const dict_index_t* index) /*!< in: an internal representation
484
of index (in the dictionary cache) */
487
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
488
ut_ad(index->cached);
490
return(index->n_uniq);
493
/********************************************************************//**
494
Gets the number of fields in the internal representation of an index
495
which uniquely determine the position of an index entry in the index, if
496
we also take multiversioning into account.
497
@return number of fields */
500
dict_index_get_n_unique_in_tree(
501
/*============================*/
502
const dict_index_t* index) /*!< in: an internal representation
503
of index (in the dictionary cache) */
506
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
507
ut_ad(index->cached);
509
if (dict_index_is_clust(index)) {
511
return(dict_index_get_n_unique(index));
514
return(dict_index_get_n_fields(index));
517
/********************************************************************//**
518
Gets the number of user-defined ordering fields in the index. In the internal
519
representation of clustered indexes we add the row id to the ordering fields
520
to make a clustered index unique, but this function returns the number of
521
fields the user defined in the index as ordering fields.
522
@return number of fields */
525
dict_index_get_n_ordering_defined_by_user(
526
/*======================================*/
527
const dict_index_t* index) /*!< in: an internal representation
528
of index (in the dictionary cache) */
530
return(index->n_user_defined_cols);
534
/********************************************************************//**
535
Gets the nth field of an index.
536
@return pointer to field object */
539
dict_index_get_nth_field(
540
/*=====================*/
541
const dict_index_t* index, /*!< in: index */
542
ulint pos) /*!< in: position of field */
545
ut_ad(pos < index->n_def);
546
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
548
return((dict_field_t*) (index->fields) + pos);
550
#endif /* UNIV_DEBUG */
552
/********************************************************************//**
553
Returns the position of a system column in an index.
554
@return position, ULINT_UNDEFINED if not contained */
557
dict_index_get_sys_col_pos(
558
/*=======================*/
559
const dict_index_t* index, /*!< in: index */
560
ulint type) /*!< in: DATA_ROW_ID, ... */
563
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
564
ut_ad(!(index->type & DICT_UNIVERSAL));
566
if (dict_index_is_clust(index)) {
568
return(dict_col_get_clust_pos(
569
dict_table_get_sys_col(index->table, type),
573
return(dict_index_get_nth_col_pos(
574
index, dict_table_get_sys_col_no(index->table, type)));
577
/*********************************************************************//**
578
Gets the field column.
579
@return field->col, pointer to the table column */
584
const dict_field_t* field) /*!< in: index field */
591
/********************************************************************//**
592
Gets pointer to the nth column in an index.
596
dict_index_get_nth_col(
597
/*===================*/
598
const dict_index_t* index, /*!< in: index */
599
ulint pos) /*!< in: position of the field */
601
return(dict_field_get_col(dict_index_get_nth_field(index, pos)));
604
/********************************************************************//**
605
Gets the column number the nth field in an index.
606
@return column number */
609
dict_index_get_nth_col_no(
610
/*======================*/
611
const dict_index_t* index, /*!< in: index */
612
ulint pos) /*!< in: position of the field */
614
return(dict_col_get_no(dict_index_get_nth_col(index, pos)));
617
#ifndef UNIV_HOTBACKUP
618
/********************************************************************//**
619
Returns the minimum data size of an index record.
620
@return minimum data size in bytes */
623
dict_index_get_min_size(
624
/*====================*/
625
const dict_index_t* index) /*!< in: index */
627
ulint n = dict_index_get_n_fields(index);
631
size += dict_col_get_min_size(dict_index_get_nth_col(index,
638
/*********************************************************************//**
639
Gets the space id of the root of the index tree.
643
dict_index_get_space(
644
/*=================*/
645
const dict_index_t* index) /*!< in: index */
648
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
650
return(index->space);
653
/*********************************************************************//**
654
Sets the space id of the root of the index tree. */
657
dict_index_set_space(
658
/*=================*/
659
dict_index_t* index, /*!< in/out: index */
660
ulint space) /*!< in: space id */
663
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
665
index->space = space;
668
/*********************************************************************//**
669
Gets the page number of the root of the index tree.
670
@return page number */
675
const dict_index_t* index) /*!< in: index */
678
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
683
/*********************************************************************//**
684
Sets the page number of the root of index tree. */
689
dict_index_t* index, /*!< in/out: index */
690
ulint page) /*!< in: page number */
693
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
698
/*********************************************************************//**
699
Gets the read-write lock of the index tree.
700
@return read-write lock */
705
dict_index_t* index) /*!< in: index */
708
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
710
return(&(index->lock));
713
/********************************************************************//**
714
Returns free space reserved for future updates of records. This is
715
relevant only in the case of many consecutive inserts, as updates
716
which make the records bigger might fragment the index.
717
@return number of free bytes on page, reserved for updates */
720
dict_index_get_space_reserve(void)
721
/*==============================*/
723
return(UNIV_PAGE_SIZE / 16);
726
/**********************************************************************//**
727
Checks if a table is in the dictionary cache.
728
@return table, NULL if not found */
731
dict_table_check_if_in_cache_low(
732
/*=============================*/
733
const char* table_name) /*!< in: table name */
739
ut_ad(mutex_own(&(dict_sys->mutex)));
741
/* Look for the table name in the hash table */
742
table_fold = ut_fold_string(table_name);
744
HASH_SEARCH(name_hash, dict_sys->table_hash, table_fold,
745
dict_table_t*, table, ut_ad(table->cached),
746
!strcmp(table->name, table_name));
750
/**********************************************************************//**
751
Gets a table; loads it to the dictionary cache if necessary. A low-level
753
@return table, NULL if not found */
758
const char* table_name) /*!< in: table name */
763
ut_ad(mutex_own(&(dict_sys->mutex)));
765
table = dict_table_check_if_in_cache_low(table_name);
768
table = dict_load_table(table_name);
771
ut_ad(!table || table->cached);
776
/**********************************************************************//**
777
Returns a table object based on table id.
778
@return table, NULL if does not exist */
781
dict_table_get_on_id_low(
782
/*=====================*/
783
dulint table_id) /*!< in: table id */
788
ut_ad(mutex_own(&(dict_sys->mutex)));
790
/* Look for the table name in the hash table */
791
fold = ut_fold_dulint(table_id);
793
HASH_SEARCH(id_hash, dict_sys->table_id_hash, fold,
794
dict_table_t*, table, ut_ad(table->cached),
795
!ut_dulint_cmp(table->id, table_id));
797
table = dict_load_table_on_id(table_id);
800
ut_ad(!table || table->cached);
802
/* TODO: should get the type information from MySQL */
806
#endif /* !UNIV_HOTBACKUP */