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 */
292
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
293
ut_ad(table->cached);
295
return(DATA_N_SYS_COLS);
298
/********************************************************************//**
299
Gets the number of all columns (also system) in a table in the dictionary
301
@return number of columns of a table */
304
dict_table_get_n_cols(
305
/*==================*/
306
const dict_table_t* table) /*!< in: table */
309
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
311
return(table->n_cols);
315
/********************************************************************//**
316
Gets the nth column of a table.
317
@return pointer to column object */
320
dict_table_get_nth_col(
321
/*===================*/
322
const dict_table_t* table, /*!< in: table */
323
ulint pos) /*!< in: position of column */
326
ut_ad(pos < table->n_def);
327
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
329
return((dict_col_t*) (table->cols) + pos);
332
/********************************************************************//**
333
Gets the given system column of a table.
334
@return pointer to column object */
337
dict_table_get_sys_col(
338
/*===================*/
339
const dict_table_t* table, /*!< in: table */
340
ulint sys) /*!< in: DATA_ROW_ID, ... */
345
ut_ad(sys < DATA_N_SYS_COLS);
346
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
348
col = dict_table_get_nth_col(table, table->n_cols
349
- DATA_N_SYS_COLS + sys);
350
ut_ad(col->mtype == DATA_SYS);
351
ut_ad(col->prtype == (sys | DATA_NOT_NULL));
355
#endif /* UNIV_DEBUG */
357
/********************************************************************//**
358
Gets the given system column number of a table.
359
@return column number */
362
dict_table_get_sys_col_no(
363
/*======================*/
364
const dict_table_t* table, /*!< in: table */
365
ulint sys) /*!< in: DATA_ROW_ID, ... */
368
ut_ad(sys < DATA_N_SYS_COLS);
369
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
371
return(table->n_cols - DATA_N_SYS_COLS + sys);
374
/********************************************************************//**
375
Check whether the table uses the compact page format.
376
@return TRUE if table uses the compact page format */
381
const dict_table_t* table) /*!< in: table */
385
#if DICT_TF_COMPACT != TRUE
389
return(UNIV_LIKELY(table->flags & DICT_TF_COMPACT));
392
/********************************************************************//**
393
Determine the file format of a table.
394
@return file format version */
397
dict_table_get_format(
398
/*==================*/
399
const dict_table_t* table) /*!< in: table */
403
return((table->flags & DICT_TF_FORMAT_MASK) >> DICT_TF_FORMAT_SHIFT);
406
/********************************************************************//**
407
Determine the file format of a table. */
410
dict_table_set_format(
411
/*==================*/
412
dict_table_t* table, /*!< in/out: table */
413
ulint format) /*!< in: file format version */
417
table->flags = (table->flags & ~DICT_TF_FORMAT_MASK)
418
| (format << DICT_TF_FORMAT_SHIFT);
421
/********************************************************************//**
422
Extract the compressed page size from table flags.
423
@return compressed page size, or 0 if not compressed */
426
dict_table_flags_to_zip_size(
427
/*=========================*/
428
ulint flags) /*!< in: flags */
430
ulint zip_size = flags & DICT_TF_ZSSIZE_MASK;
432
if (UNIV_UNLIKELY(zip_size)) {
433
zip_size = ((PAGE_ZIP_MIN_SIZE >> 1)
434
<< (zip_size >> DICT_TF_ZSSIZE_SHIFT));
436
ut_ad(zip_size <= UNIV_PAGE_SIZE);
442
/********************************************************************//**
443
Check whether the table uses the compressed compact page format.
444
@return compressed page size, or 0 if not compressed */
449
const dict_table_t* table) /*!< in: table */
453
return(dict_table_flags_to_zip_size(table->flags));
456
/********************************************************************//**
457
Gets the number of fields in the internal representation of an index,
458
including fields added by the dictionary system.
459
@return number of fields */
462
dict_index_get_n_fields(
463
/*====================*/
464
const dict_index_t* index) /*!< in: an internal
465
representation of index (in
466
the dictionary cache) */
469
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
471
return(index->n_fields);
474
/********************************************************************//**
475
Gets the number of fields in the internal representation of an index
476
that uniquely determine the position of an index entry in the index, if
477
we do not take multiversioning into account: in the B-tree use the value
478
returned by dict_index_get_n_unique_in_tree.
479
@return number of fields */
482
dict_index_get_n_unique(
483
/*====================*/
484
const dict_index_t* index) /*!< in: an internal representation
485
of index (in the dictionary cache) */
488
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
489
ut_ad(index->cached);
491
return(index->n_uniq);
494
/********************************************************************//**
495
Gets the number of fields in the internal representation of an index
496
which uniquely determine the position of an index entry in the index, if
497
we also take multiversioning into account.
498
@return number of fields */
501
dict_index_get_n_unique_in_tree(
502
/*============================*/
503
const dict_index_t* index) /*!< in: an internal representation
504
of index (in the dictionary cache) */
507
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
508
ut_ad(index->cached);
510
if (dict_index_is_clust(index)) {
512
return(dict_index_get_n_unique(index));
515
return(dict_index_get_n_fields(index));
518
/********************************************************************//**
519
Gets the number of user-defined ordering fields in the index. In the internal
520
representation of clustered indexes we add the row id to the ordering fields
521
to make a clustered index unique, but this function returns the number of
522
fields the user defined in the index as ordering fields.
523
@return number of fields */
526
dict_index_get_n_ordering_defined_by_user(
527
/*======================================*/
528
const dict_index_t* index) /*!< in: an internal representation
529
of index (in the dictionary cache) */
531
return(index->n_user_defined_cols);
535
/********************************************************************//**
536
Gets the nth field of an index.
537
@return pointer to field object */
540
dict_index_get_nth_field(
541
/*=====================*/
542
const dict_index_t* index, /*!< in: index */
543
ulint pos) /*!< in: position of field */
546
ut_ad(pos < index->n_def);
547
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
549
return((dict_field_t*) (index->fields) + pos);
551
#endif /* UNIV_DEBUG */
553
/********************************************************************//**
554
Returns the position of a system column in an index.
555
@return position, ULINT_UNDEFINED if not contained */
558
dict_index_get_sys_col_pos(
559
/*=======================*/
560
const dict_index_t* index, /*!< in: index */
561
ulint type) /*!< in: DATA_ROW_ID, ... */
564
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
565
ut_ad(!(index->type & DICT_UNIVERSAL));
567
if (dict_index_is_clust(index)) {
569
return(dict_col_get_clust_pos(
570
dict_table_get_sys_col(index->table, type),
574
return(dict_index_get_nth_col_pos(
575
index, dict_table_get_sys_col_no(index->table, type)));
578
/*********************************************************************//**
579
Gets the field column.
580
@return field->col, pointer to the table column */
585
const dict_field_t* field) /*!< in: index field */
592
/********************************************************************//**
593
Gets pointer to the nth column in an index.
597
dict_index_get_nth_col(
598
/*===================*/
599
const dict_index_t* index, /*!< in: index */
600
ulint pos) /*!< in: position of the field */
602
return(dict_field_get_col(dict_index_get_nth_field(index, pos)));
605
/********************************************************************//**
606
Gets the column number the nth field in an index.
607
@return column number */
610
dict_index_get_nth_col_no(
611
/*======================*/
612
const dict_index_t* index, /*!< in: index */
613
ulint pos) /*!< in: position of the field */
615
return(dict_col_get_no(dict_index_get_nth_col(index, pos)));
618
#ifndef UNIV_HOTBACKUP
619
/********************************************************************//**
620
Returns the minimum data size of an index record.
621
@return minimum data size in bytes */
624
dict_index_get_min_size(
625
/*====================*/
626
const dict_index_t* index) /*!< in: index */
628
ulint n = dict_index_get_n_fields(index);
632
size += dict_col_get_min_size(dict_index_get_nth_col(index,
639
/*********************************************************************//**
640
Gets the space id of the root of the index tree.
644
dict_index_get_space(
645
/*=================*/
646
const dict_index_t* index) /*!< in: index */
649
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
651
return(index->space);
654
/*********************************************************************//**
655
Sets the space id of the root of the index tree. */
658
dict_index_set_space(
659
/*=================*/
660
dict_index_t* index, /*!< in/out: index */
661
ulint space) /*!< in: space id */
664
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
666
index->space = space;
669
/*********************************************************************//**
670
Gets the page number of the root of the index tree.
671
@return page number */
676
const dict_index_t* index) /*!< in: index */
679
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
684
/*********************************************************************//**
685
Sets the page number of the root of index tree. */
690
dict_index_t* index, /*!< in/out: index */
691
ulint page) /*!< in: page number */
694
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
699
/*********************************************************************//**
700
Gets the read-write lock of the index tree.
701
@return read-write lock */
706
dict_index_t* index) /*!< in: index */
709
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
711
return(&(index->lock));
714
/********************************************************************//**
715
Returns free space reserved for future updates of records. This is
716
relevant only in the case of many consecutive inserts, as updates
717
which make the records bigger might fragment the index.
718
@return number of free bytes on page, reserved for updates */
721
dict_index_get_space_reserve(void)
722
/*==============================*/
724
return(UNIV_PAGE_SIZE / 16);
727
/**********************************************************************//**
728
Checks if a table is in the dictionary cache.
729
@return table, NULL if not found */
732
dict_table_check_if_in_cache_low(
733
/*=============================*/
734
const char* table_name) /*!< in: table name */
740
ut_ad(mutex_own(&(dict_sys->mutex)));
742
/* Look for the table name in the hash table */
743
table_fold = ut_fold_string(table_name);
745
HASH_SEARCH(name_hash, dict_sys->table_hash, table_fold,
746
dict_table_t*, table, ut_ad(table->cached),
747
!strcmp(table->name, table_name));
751
/**********************************************************************//**
752
Gets a table; loads it to the dictionary cache if necessary. A low-level
754
@return table, NULL if not found */
759
const char* table_name) /*!< in: table name */
764
ut_ad(mutex_own(&(dict_sys->mutex)));
766
table = dict_table_check_if_in_cache_low(table_name);
769
table = dict_load_table(table_name);
772
ut_ad(!table || table->cached);
777
/**********************************************************************//**
778
Returns a table object based on table id.
779
@return table, NULL if does not exist */
782
dict_table_get_on_id_low(
783
/*=====================*/
784
dulint table_id) /*!< in: table id */
789
ut_ad(mutex_own(&(dict_sys->mutex)));
791
/* Look for the table name in the hash table */
792
fold = ut_fold_dulint(table_id);
794
HASH_SEARCH(id_hash, dict_sys->table_id_hash, fold,
795
dict_table_t*, table, ut_ad(table->cached),
796
!ut_dulint_cmp(table->id, table_id));
798
table = dict_load_table_on_id(table_id);
801
ut_ad(!table || table->cached);
803
/* TODO: should get the type information from MySQL */
807
#endif /* !UNIV_HOTBACKUP */