dict0dict.ic 44.6 KB
Newer Older
Vadim Tkachenko's avatar
Vadim Tkachenko committed
1 2
/*****************************************************************************

Sergei Golubchik's avatar
Sergei Golubchik committed
3
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
4
Copyright (c) 2013, 2017, MariaDB Corporation.
Vadim Tkachenko's avatar
Vadim Tkachenko committed
5 6 7 8 9 10 11 12 13 14

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; version 2 of the License.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
Sergei Golubchik's avatar
Sergei Golubchik committed
15 16
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
Vadim Tkachenko's avatar
Vadim Tkachenko committed
17 18 19

*****************************************************************************/

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
20 21
/******************************************************************//**
@file include/dict0dict.ic
22 23 24 25 26
Data dictionary system

Created 1/8/1996 Heikki Tuuri
***********************************************************************/

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
27 28
#include "data0type.h"
#ifndef UNIV_HOTBACKUP
29 30
#include "dict0load.h"
#include "rem0types.h"
31
#include "fsp0fsp.h"
32
#include "srv0srv.h"
33
#include "sync0rw.h" /* RW_S_LATCH */
34

Sergei Golubchik's avatar
Sergei Golubchik committed
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
/*********************************************************************//**
Gets the minimum number of bytes per character.
@return minimum multi-byte char size, in bytes */
UNIV_INLINE
ulint
dict_col_get_mbminlen(
/*==================*/
	const dict_col_t*	col)	/*!< in: column */
{
	return(DATA_MBMINLEN(col->mbminmaxlen));
}
/*********************************************************************//**
Gets the maximum number of bytes per character.
@return maximum multi-byte char size, in bytes */
UNIV_INLINE
ulint
dict_col_get_mbmaxlen(
/*==================*/
	const dict_col_t*	col)	/*!< in: column */
{
	return(DATA_MBMAXLEN(col->mbminmaxlen));
}
/*********************************************************************//**
Sets the minimum and maximum number of bytes per character. */
UNIV_INLINE
void
dict_col_set_mbminmaxlen(
/*=====================*/
	dict_col_t*	col,		/*!< in/out: column */
	ulint		mbminlen,	/*!< in: minimum multi-byte
					character size, in bytes */
	ulint		mbmaxlen)	/*!< in: minimum multi-byte
					character size, in bytes */
{
	ut_ad(mbminlen < DATA_MBMAX);
	ut_ad(mbmaxlen < DATA_MBMAX);
	ut_ad(mbminlen <= mbmaxlen);

	col->mbminmaxlen = DATA_MBMINMAXLEN(mbminlen, mbmaxlen);
}
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
75
/*********************************************************************//**
76 77 78 79 80
Gets the column data type. */
UNIV_INLINE
void
dict_col_copy_type(
/*===============*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
81 82
	const dict_col_t*	col,	/*!< in: column */
	dtype_t*		type)	/*!< out: data type */
83
{
Sergei Golubchik's avatar
Sergei Golubchik committed
84 85
	ut_ad(col != NULL);
	ut_ad(type != NULL);
86 87 88 89

	type->mtype = col->mtype;
	type->prtype = col->prtype;
	type->len = col->len;
Sergei Golubchik's avatar
Sergei Golubchik committed
90
	type->mbminmaxlen = col->mbminmaxlen;
91
}
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
92
#endif /* !UNIV_HOTBACKUP */
93 94

#ifdef UNIV_DEBUG
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
95 96 97
/*********************************************************************//**
Assert that a column and a data type match.
@return	TRUE */
98 99 100 101
UNIV_INLINE
ibool
dict_col_type_assert_equal(
/*=======================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
102 103
	const dict_col_t*	col,	/*!< in: column */
	const dtype_t*		type)	/*!< in: data type */
104 105 106 107 108 109
{
	ut_ad(col);
	ut_ad(type);

	ut_ad(col->mtype == type->mtype);
	ut_ad(col->prtype == type->prtype);
110
	//ut_ad(col->len == type->len);
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
111
# ifndef UNIV_HOTBACKUP
Sergei Golubchik's avatar
Sergei Golubchik committed
112
	ut_ad(col->mbminmaxlen == type->mbminmaxlen);
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
113
# endif /* !UNIV_HOTBACKUP */
114 115 116 117 118

	return(TRUE);
}
#endif /* UNIV_DEBUG */

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
119 120 121 122
#ifndef UNIV_HOTBACKUP
/***********************************************************************//**
Returns the minimum size of the column.
@return	minimum size */
123 124 125 126
UNIV_INLINE
ulint
dict_col_get_min_size(
/*==================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
127
	const dict_col_t*	col)	/*!< in: column */
128 129
{
	return(dtype_get_min_size_low(col->mtype, col->prtype, col->len,
Sergei Golubchik's avatar
Sergei Golubchik committed
130
				      col->mbminmaxlen));
131
}
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
132 133 134
/***********************************************************************//**
Returns the maximum size of the column.
@return	maximum size */
135 136 137 138
UNIV_INLINE
ulint
dict_col_get_max_size(
/*==================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
139
	const dict_col_t*	col)	/*!< in: column */
140 141 142
{
	return(dtype_get_max_size_low(col->mtype, col->len));
}
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
143 144 145 146
#endif /* !UNIV_HOTBACKUP */
/***********************************************************************//**
Returns the size of a fixed size column, 0 if not a fixed size column.
@return	fixed size, or 0 */
147 148 149 150
UNIV_INLINE
ulint
dict_col_get_fixed_size(
/*====================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
151
	const dict_col_t*	col,	/*!< in: column */
152
	ulint			comp)	/*!< in: nonzero=ROW_FORMAT=COMPACT */
153 154
{
	return(dtype_get_fixed_size_low(col->mtype, col->prtype, col->len,
Sergei Golubchik's avatar
Sergei Golubchik committed
155
					col->mbminmaxlen, comp));
156
}
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
157
/***********************************************************************//**
158
Returns the ROW_FORMAT=REDUNDANT stored SQL NULL size of a column.
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
159 160
For fixed length types it is the fixed length of the type, otherwise 0.
@return	SQL null storage size in ROW_FORMAT=REDUNDANT */
161 162 163 164
UNIV_INLINE
ulint
dict_col_get_sql_null_size(
/*=======================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
165 166
	const dict_col_t*	col,	/*!< in: column */
	ulint			comp)	/*!< in: nonzero=ROW_FORMAT=COMPACT  */
167
{
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
168
	return(dict_col_get_fixed_size(col, comp));
169 170
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
171 172 173
/*********************************************************************//**
Gets the column number.
@return	col->ind, table column position (starting from 0) */
174 175 176 177
UNIV_INLINE
ulint
dict_col_get_no(
/*============*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
178
	const dict_col_t*	col)	/*!< in: column */
179 180 181 182 183 184
{
	ut_ad(col);

	return(col->ind);
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
185
/*********************************************************************//**
186 187 188 189 190
Gets the column position in the clustered index. */
UNIV_INLINE
ulint
dict_col_get_clust_pos(
/*===================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
191 192
	const dict_col_t*	col,		/*!< in: table column */
	const dict_index_t*	clust_index)	/*!< in: clustered index */
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
{
	ulint	i;

	ut_ad(col);
	ut_ad(clust_index);
	ut_ad(dict_index_is_clust(clust_index));

	for (i = 0; i < clust_index->n_def; i++) {
		const dict_field_t*	field = &clust_index->fields[i];

		if (!field->prefix_len && field->col == col) {
			return(i);
		}
	}

	return(ULINT_UNDEFINED);
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
211
#ifndef UNIV_HOTBACKUP
212
#ifdef UNIV_DEBUG
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
213 214 215
/********************************************************************//**
Gets the first index on the table (the clustered index).
@return	index, NULL if none exists */
216 217 218 219
UNIV_INLINE
dict_index_t*
dict_table_get_first_index(
/*=======================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
220
	const dict_table_t*	table)	/*!< in: table */
221 222 223 224 225 226 227
{
	ut_ad(table);
	ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);

	return(UT_LIST_GET_FIRST(((dict_table_t*) table)->indexes));
}

228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
/********************************************************************//**
Gets the last index on the table.
@return	index, NULL if none exists */
UNIV_INLINE
dict_index_t*
dict_table_get_last_index(
/*=======================*/
	const dict_table_t*	table)	/*!< in: table */
{
	ut_ad(table);
	ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);

	return(UT_LIST_GET_LAST((const_cast<dict_table_t*>(table))
				->indexes));
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
244 245 246
/********************************************************************//**
Gets the next index on the table.
@return	index, NULL if none left */
247 248 249 250
UNIV_INLINE
dict_index_t*
dict_table_get_next_index(
/*======================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
251
	const dict_index_t*	index)	/*!< in: index */
252 253 254 255 256 257 258
{
	ut_ad(index);
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);

	return(UT_LIST_GET_NEXT(indexes, (dict_index_t*) index));
}
#endif /* UNIV_DEBUG */
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
259
#endif /* !UNIV_HOTBACKUP */
260

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
261 262 263
/********************************************************************//**
Check whether the index is the clustered index.
@return	nonzero for clustered index, zero for other indexes */
264 265 266 267
UNIV_INLINE
ulint
dict_index_is_clust(
/*================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
268
	const dict_index_t*	index)	/*!< in: index */
269 270 271
{
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);

272
	return(index->type & DICT_CLUSTERED);
273
}
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
274 275 276
/********************************************************************//**
Check whether the index is unique.
@return	nonzero for unique index, zero for other indexes */
277 278 279 280
UNIV_INLINE
ulint
dict_index_is_unique(
/*=================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
281
	const dict_index_t*	index)	/*!< in: index */
282 283 284
{
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);

285
	return(index->type & DICT_UNIQUE);
286 287
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
288 289 290
/********************************************************************//**
Check whether the index is the insert buffer tree.
@return	nonzero for insert buffer, zero for other indexes */
291 292 293 294
UNIV_INLINE
ulint
dict_index_is_ibuf(
/*===============*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
295
	const dict_index_t*	index)	/*!< in: index */
296 297 298
{
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);

299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314
	return(index->type & DICT_IBUF);
}

/********************************************************************//**
Check whether the index is an universal index tree.
@return	nonzero for universal tree, zero for other indexes */
UNIV_INLINE
ulint
dict_index_is_univ(
/*===============*/
	const dict_index_t*	index)	/*!< in: index */
{
	ut_ad(index);
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);

	return(index->type & DICT_UNIVERSAL);
315 316
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
/********************************************************************//**
Check whether the index is a secondary index or the insert buffer tree.
@return	nonzero for insert buffer, zero for other indexes */
UNIV_INLINE
ulint
dict_index_is_sec_or_ibuf(
/*======================*/
	const dict_index_t*	index)	/*!< in: index */
{
	ulint	type;

	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);

	type = index->type;

332
	return(!(type & DICT_CLUSTERED) || (type & DICT_IBUF));
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
333 334 335
}

/********************************************************************//**
336
Gets the number of user-defined columns in a table in the dictionary
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
337 338
cache.
@return	number of user-defined (e.g., not ROW_ID) columns of a table */
339 340 341 342
UNIV_INLINE
ulint
dict_table_get_n_user_cols(
/*=======================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
343
	const dict_table_t*	table)	/*!< in: table */
344 345 346 347 348 349
{
	ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);

	return(table->n_cols - DATA_N_SYS_COLS);
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
350 351 352
/********************************************************************//**
Gets the number of system columns in a table in the dictionary cache.
@return	number of system (e.g., ROW_ID) columns of a table */
353 354 355 356
UNIV_INLINE
ulint
dict_table_get_n_sys_cols(
/*======================*/
Sergei Golubchik's avatar
Sergei Golubchik committed
357
	const dict_table_t*	table MY_ATTRIBUTE((unused)))	/*!< in: table */
358 359 360 361 362 363 364 365
{
	ut_ad(table);
	ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
	ut_ad(table->cached);

	return(DATA_N_SYS_COLS);
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
366
/********************************************************************//**
367
Gets the number of all columns (also system) in a table in the dictionary
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
368 369
cache.
@return	number of columns of a table */
370 371 372 373
UNIV_INLINE
ulint
dict_table_get_n_cols(
/*==================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
374
	const dict_table_t*	table)	/*!< in: table */
375 376 377 378 379 380
{
	ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);

	return(table->n_cols);
}

381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430
/********************************************************************//**
Gets the approximately estimated number of rows in the table.
@return	estimated number of rows */
UNIV_INLINE
ib_uint64_t
dict_table_get_n_rows(
/*==================*/
	const dict_table_t*	table)	/*!< in: table */
{
	ut_ad(table->stat_initialized);

	return(table->stat_n_rows);
}

/********************************************************************//**
Increment the number of rows in the table by one.
Notice that this operation is not protected by any latch, the number is
approximate. */
UNIV_INLINE
void
dict_table_n_rows_inc(
/*==================*/
	dict_table_t*	table)	/*!< in/out: table */
{
	if (table->stat_initialized) {
		ib_uint64_t	n_rows = table->stat_n_rows;
		if (n_rows < 0xFFFFFFFFFFFFFFFFULL) {
			table->stat_n_rows = n_rows + 1;
		}
	}
}

/********************************************************************//**
Decrement the number of rows in the table by one.
Notice that this operation is not protected by any latch, the number is
approximate. */
UNIV_INLINE
void
dict_table_n_rows_dec(
/*==================*/
	dict_table_t*	table)	/*!< in/out: table */
{
	if (table->stat_initialized) {
		ib_uint64_t	n_rows = table->stat_n_rows;
		if (n_rows > 0) {
			table->stat_n_rows = n_rows - 1;
		}
	}
}

431
#ifdef UNIV_DEBUG
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
432 433 434
/********************************************************************//**
Gets the nth column of a table.
@return	pointer to column object */
435 436 437 438
UNIV_INLINE
dict_col_t*
dict_table_get_nth_col(
/*===================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
439 440
	const dict_table_t*	table,	/*!< in: table */
	ulint			pos)	/*!< in: position of column */
441 442 443 444 445 446 447 448
{
	ut_ad(table);
	ut_ad(pos < table->n_def);
	ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);

	return((dict_col_t*) (table->cols) + pos);
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
449 450 451
/********************************************************************//**
Gets the given system column of a table.
@return	pointer to column object */
452 453 454 455
UNIV_INLINE
dict_col_t*
dict_table_get_sys_col(
/*===================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
456 457
	const dict_table_t*	table,	/*!< in: table */
	ulint			sys)	/*!< in: DATA_ROW_ID, ... */
458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
{
	dict_col_t*	col;

	ut_ad(table);
	ut_ad(sys < DATA_N_SYS_COLS);
	ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);

	col = dict_table_get_nth_col(table, table->n_cols
				     - DATA_N_SYS_COLS + sys);
	ut_ad(col->mtype == DATA_SYS);
	ut_ad(col->prtype == (sys | DATA_NOT_NULL));

	return(col);
}
#endif /* UNIV_DEBUG */

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
474 475 476
/********************************************************************//**
Gets the given system column number of a table.
@return	column number */
477 478 479 480
UNIV_INLINE
ulint
dict_table_get_sys_col_no(
/*======================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
481 482
	const dict_table_t*	table,	/*!< in: table */
	ulint			sys)	/*!< in: DATA_ROW_ID, ... */
483 484 485 486 487 488 489 490
{
	ut_ad(table);
	ut_ad(sys < DATA_N_SYS_COLS);
	ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);

	return(table->n_cols - DATA_N_SYS_COLS + sys);
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
491 492 493
/********************************************************************//**
Check whether the table uses the compact page format.
@return	TRUE if table uses the compact page format */
494 495 496 497
UNIV_INLINE
ibool
dict_table_is_comp(
/*===============*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
498
	const dict_table_t*	table)	/*!< in: table */
499 500 501
{
	ut_ad(table);

502 503
#if DICT_TF_COMPACT != 1
#error "DICT_TF_COMPACT must be 1"
504 505
#endif

506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535
	return(table->flags & DICT_TF_COMPACT);
}

/************************************************************************
Check if the table has an FTS index. */
UNIV_INLINE
ibool
dict_table_has_fts_index(
/*=====================*/
				/* out: TRUE if table has an FTS index */
	dict_table_t*   table)  /* in: table */
{
	ut_ad(table);

	return(DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS));
}

/********************************************************************//**
Validate the table flags.
@return	true if valid. */
UNIV_INLINE
bool
dict_tf_is_valid(
/*=============*/
	ulint	flags)		/*!< in: table flags */
{
	ulint	compact = DICT_TF_GET_COMPACT(flags);
	ulint	zip_ssize = DICT_TF_GET_ZIP_SSIZE(flags);
	ulint	atomic_blobs = DICT_TF_HAS_ATOMIC_BLOBS(flags);
	ulint	unused = DICT_TF_GET_UNUSED(flags);
536 537 538 539
	ulint	page_compression = DICT_TF_GET_PAGE_COMPRESSION(flags);
	ulint	page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL(flags);
	ulint	data_dir = DICT_TF_HAS_DATA_DIR(flags);
	ulint	atomic_writes = DICT_TF_GET_ATOMIC_WRITES(flags);
540 541 542

	/* Make sure there are no bits that we do not know about. */
	if (unused != 0) {
543
		fprintf(stderr,
544
			"InnoDB: Error: table unused flags are " ULINTPF
545 546
			" in the data dictionary and are corrupted\n"
			"InnoDB: Error: data dictionary flags are\n"
547 548 549 550 551 552
			"InnoDB: compact " ULINTPF " atomic_blobs " ULINTPF
			"\nInnoDB: unused " ULINTPF " data_dir " ULINTPF
			" zip_ssize " ULINTPF
			"\nInnoDB: page_compression " ULINTPF
			" page_compression_level " ULINTPF
			"\nInnoDB: atomic_writes " ULINTPF "\n",
553 554
			unused,
			compact, atomic_blobs, unused, data_dir, zip_ssize,
555
			page_compression, page_compression_level, atomic_writes
556 557
		);

558 559 560 561 562 563 564 565 566
		return(false);

	} else if (atomic_blobs) {
		/* Barracuda row formats COMPRESSED and DYNAMIC build on
		the page structure introduced for the COMPACT row format
		by allowing keys in secondary indexes to be made from
		data stored off-page in the clustered index. */

		if (!compact) {
567
			fprintf(stderr,
568 569
				"InnoDB: Error: table compact flags are "
				ULINTPF
570 571
				" in the data dictionary and are corrupted\n"
				"InnoDB: Error: data dictionary flags are\n"
572 573 574 575 576 577 578
				"InnoDB: compact " ULINTPF
				" atomic_blobs " ULINTPF "\n"
				"InnoDB: unused " ULINTPF
				" data_dir " ULINTPF " zip_ssize " ULINTPF
				"\nInnoDB: page_compression " ULINTPF
				" page_compression_level " ULINTPF
				"\nInnoDB: atomic_writes " ULINTPF "\n",
579 580 581
				compact, compact, atomic_blobs, unused, data_dir, zip_ssize,
				page_compression, page_compression_level, atomic_writes
			);
582 583 584 585 586 587
			return(false);
		}

	} else if (zip_ssize) {

		/* Antelope does not support COMPRESSED row format. */
588
		fprintf(stderr,
589
			"InnoDB: Error: table flags are " ULINTPF
590 591
			" in the data dictionary and are corrupted\n"
			"InnoDB: Error: data dictionary flags are\n"
592 593 594 595 596 597
			"InnoDB: compact " ULINTPF " atomic_blobs " ULINTPF
			"\nInnoDB: unused " ULINTPF " data_dir " ULINTPF
			" zip_ssize " ULINTPF
			"\nInnoDB: page_compression " ULINTPF
			" page_compression_level " ULINTPF
			"\nInnoDB: atomic_writes " ULINTPF "\n",
598 599 600
			flags, compact, atomic_blobs, unused, data_dir, zip_ssize,
			page_compression, page_compression_level, atomic_writes
		);
601 602 603 604 605 606 607 608 609 610 611 612
		return(false);
	}

	if (zip_ssize) {

		/* COMPRESSED row format must have compact and atomic_blobs
		bits set and validate the number is within allowed range. */

		if (!compact
		    || !atomic_blobs
		    || zip_ssize > PAGE_ZIP_SSIZE_MAX) {

613
			fprintf(stderr,
614 615 616
				"InnoDB: Error: table compact flags are "
				ULINTPF
				" in the data dictionary and are corrupted\n"
617
				"InnoDB: Error: data dictionary flags are\n"
618 619 620 621 622 623 624
				"InnoDB: compact " ULINTPF
				" atomic_blobs " ULINTPF "\n"
				"InnoDB: unused " ULINTPF
				" data_dir " ULINTPF " zip_ssize " ULINTPF
				"\nInnoDB: page_compression " ULINTPF
				" page_compression_level " ULINTPF
				"\nInnoDB: atomic_writes " ULINTPF "\n",
625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642
				flags,
				compact, atomic_blobs, unused, data_dir, zip_ssize,
				page_compression, page_compression_level, atomic_writes

			);
			return(false);
		}
	}

        if (page_compression || page_compression_level) {
		/* Page compression format must have compact and
		atomic_blobs and page_compression_level requires
		page_compression */
		if (!compact
			|| !page_compression
			|| !atomic_blobs) {

			fprintf(stderr,
643 644
				"InnoDB: Error: table flags are " ULINTPF
				" in the data dictionary and are corrupted\n"
645
				"InnoDB: Error: data dictionary flags are\n"
646 647 648 649 650 651 652
				"InnoDB: compact " ULINTPF
				" atomic_blobs " ULINTPF "\n"
				"InnoDB: unused " ULINTPF
				" data_dir " ULINTPF " zip_ssize " ULINTPF
				"\nInnoDB: page_compression " ULINTPF
				" page_compression_level " ULINTPF
				"\nInnoDB: atomic_writes " ULINTPF "\n",
653 654 655
				flags, compact, atomic_blobs, unused, data_dir, zip_ssize,
				page_compression, page_compression_level, atomic_writes
			);
656 657 658 659
			return(false);
		}
	}

660 661
	if (atomic_writes) {

662
		if(atomic_writes > ATOMIC_WRITES_OFF) {
663 664

			fprintf(stderr,
665 666
				"InnoDB: Error: table flags are " ULINTPF
				" in the data dictionary and are corrupted\n"
667
				"InnoDB: Error: data dictionary flags are\n"
668 669 670 671 672 673 674
				"InnoDB: compact " ULINTPF
				" atomic_blobs " ULINTPF "\n"
				"InnoDB: unused " ULINTPF
				" data_dir " ULINTPF " zip_ssize " ULINTPF
				"\nInnoDB: page_compression " ULINTPF
				" page_compression_level " ULINTPF
				"\nInnoDB: atomic_writes " ULINTPF "\n",
675 676 677
				flags, compact, atomic_blobs, unused, data_dir, zip_ssize,
				page_compression, page_compression_level, atomic_writes
			);
678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703
			return(false);
		}
	}

	/* CREATE TABLE ... DATA DIRECTORY is supported for any row format,
	so the DATA_DIR flag is compatible with all other table flags. */

	return(true);
}

/********************************************************************//**
Validate a SYS_TABLES TYPE field and return it.
@return	Same as input after validating it as a SYS_TABLES TYPE field.
If there is an error, return ULINT_UNDEFINED. */
UNIV_INLINE
ulint
dict_sys_tables_type_validate(
/*==========================*/
	ulint	type,		/*!< in: SYS_TABLES.TYPE */
	ulint	n_cols)		/*!< in: SYS_TABLES.N_COLS */
{
	ulint	low_order_bit = DICT_TF_GET_COMPACT(type);
	ulint	redundant = !(n_cols & DICT_N_COLS_COMPACT);
	ulint	zip_ssize = DICT_TF_GET_ZIP_SSIZE(type);
	ulint	atomic_blobs = DICT_TF_HAS_ATOMIC_BLOBS(type);
	ulint	unused = DICT_TF_GET_UNUSED(type);
704 705 706
	ulint	page_compression = DICT_TF_GET_PAGE_COMPRESSION(type);
	ulint	page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL(type);
	ulint	atomic_writes = DICT_TF_GET_ATOMIC_WRITES(type);
707

708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758
	/* The low order bit of SYS_TABLES.TYPE is always set to 1.
	If the format is UNIV_FORMAT_B or higher, this field is the same
	as dict_table_t::flags. Zero is not allowed here. */
	if (!low_order_bit) {
		return(ULINT_UNDEFINED);
	}

	if (redundant) {
		if (zip_ssize || atomic_blobs) {
			return(ULINT_UNDEFINED);
		}
	}

	/* Make sure there are no bits that we do not know about. */
	if (unused) {
		return(ULINT_UNDEFINED);
	}

	if (atomic_blobs) {
		/* Barracuda row formats COMPRESSED and DYNAMIC build on
		the page structure introduced for the COMPACT row format
		by allowing keys in secondary indexes to be made from
		data stored off-page in the clustered index.

		The DICT_N_COLS_COMPACT flag should be in N_COLS,
		but we already know that. */
	} else if (zip_ssize) {
		/* Antelope does not support COMPRESSED format. */
		return(ULINT_UNDEFINED);
	}

	if (zip_ssize) {
		/* COMPRESSED row format must have low_order_bit and
		atomic_blobs bits set and the DICT_N_COLS_COMPACT flag
		should be in N_COLS, but we already know about the
		low_order_bit and DICT_N_COLS_COMPACT flags. */
		if (!atomic_blobs) {
			return(ULINT_UNDEFINED);
		}

		/* Validate that the number is within allowed range. */
		if (zip_ssize > PAGE_ZIP_SSIZE_MAX) {
			return(ULINT_UNDEFINED);
		}
	}

	/* There is nothing to validate for the data_dir field.
	CREATE TABLE ... DATA DIRECTORY is supported for any row
	format, so the DATA_DIR flag is compatible with any other
	table flags. However, it is not used with TEMPORARY tables.*/

759 760 761 762 763 764 765 766 767 768 769
        if (page_compression || page_compression_level) {
		/* page compressed row format must have low_order_bit and
		atomic_blobs bits set and the DICT_N_COLS_COMPACT flag
		should be in N_COLS, but we already know about the
		low_order_bit and DICT_N_COLS_COMPACT flags. */

                if (!atomic_blobs || !page_compression) {
			return(ULINT_UNDEFINED);
		}
	}

770
	/* Validate that the atomic writes number is within allowed range. */
771
	if (atomic_writes > ATOMIC_WRITES_OFF) {
772
		return(ULINT_UNDEFINED);
773 774
	}

775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820
	/* Return the validated SYS_TABLES.TYPE. */
	return(type);
}

/********************************************************************//**
Determine the file format from dict_table_t::flags
The low order bit will be zero for REDUNDANT and 1 for COMPACT. For any
other row_format, file_format is > 0 and DICT_TF_COMPACT will also be set.
@return	file format version */
UNIV_INLINE
rec_format_t
dict_tf_get_rec_format(
/*===================*/
	ulint		flags)	/*!< in: dict_table_t::flags */
{
	ut_a(dict_tf_is_valid(flags));

	if (!DICT_TF_GET_COMPACT(flags)) {
		return(REC_FORMAT_REDUNDANT);
	}

	if (!DICT_TF_HAS_ATOMIC_BLOBS(flags)) {
		return(REC_FORMAT_COMPACT);
	}

	if (DICT_TF_GET_ZIP_SSIZE(flags)) {
		return(REC_FORMAT_COMPRESSED);
	}

	return(REC_FORMAT_DYNAMIC);
}

/********************************************************************//**
Determine the file format from a dict_table_t::flags.
@return	file format version */
UNIV_INLINE
ulint
dict_tf_get_format(
/*===============*/
	ulint		flags)	/*!< in: dict_table_t::flags */
{
	if (DICT_TF_HAS_ATOMIC_BLOBS(flags)) {
		return(UNIV_FORMAT_B);
	}

	return(UNIV_FORMAT_A);
821 822
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
823 824 825
/********************************************************************//**
Determine the file format of a table.
@return	file format version */
826 827 828 829
UNIV_INLINE
ulint
dict_table_get_format(
/*==================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
830
	const dict_table_t*	table)	/*!< in: table */
831 832 833
{
	ut_ad(table);

834
	return(dict_tf_get_format(table->flags));
835 836
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
837
/********************************************************************//**
838 839
Set the file format and zip size in a dict_table_t::flags.  If zip size
is not needed, it should be 0. */
840 841
UNIV_INLINE
void
842 843 844 845 846
dict_tf_set(
/*========*/
	ulint*		flags,		/*!< in/out: table flags */
	rec_format_t	format,		/*!< in: file format */
	ulint		zip_ssize,	/*!< in: zip shift size */
847 848 849 850 851 852
	bool		use_data_dir,	/*!< in: table uses DATA DIRECTORY
					*/
	bool		page_compressed,/*!< in: table uses page compressed
					pages */
	ulint		page_compression_level, /*!< in: table page compression
						 level */
853
	ulint		atomic_writes)  /*!< in: table atomic writes setup */
854
{
855 856
	atomic_writes_t awrites = (atomic_writes_t)atomic_writes;

857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876
	switch (format) {
	case REC_FORMAT_REDUNDANT:
		*flags = 0;
		ut_ad(zip_ssize == 0);
		break;
	case REC_FORMAT_COMPACT:
		*flags = DICT_TF_COMPACT;
		ut_ad(zip_ssize == 0);
		break;
	case REC_FORMAT_COMPRESSED:
		*flags = DICT_TF_COMPACT
			| (1 << DICT_TF_POS_ATOMIC_BLOBS)
			| (zip_ssize << DICT_TF_POS_ZIP_SSIZE);
		break;
	case REC_FORMAT_DYNAMIC:
		*flags = DICT_TF_COMPACT
			| (1 << DICT_TF_POS_ATOMIC_BLOBS);
		ut_ad(zip_ssize == 0);
		break;
	}
877

878 879 880
	if (use_data_dir) {
		*flags |= (1 << DICT_TF_POS_DATA_DIR);
	}
881 882

	if (page_compressed) {
883 884 885
		*flags |= (1 << DICT_TF_POS_ATOMIC_BLOBS)
                       | (1 << DICT_TF_POS_PAGE_COMPRESSION)
		       | (page_compression_level << DICT_TF_POS_PAGE_COMPRESSION_LEVEL);
886 887 888 889 890 891

		ut_ad(zip_ssize == 0);
		ut_ad(dict_tf_get_page_compression(*flags) == TRUE);
		ut_ad(dict_tf_get_page_compression_level(*flags) == page_compression_level);
	}

892
	*flags |= (atomic_writes << DICT_TF_POS_ATOMIC_WRITES);
Jan Lindström's avatar
Jan Lindström committed
893
	ut_a(dict_tf_get_atomic_writes(*flags) == awrites);
894 895
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
896
/********************************************************************//**
897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913
Convert a 32 bit integer table flags to the 32 bit integer that is
written into the tablespace header at the offset FSP_SPACE_FLAGS and is
also stored in the fil_space_t::flags field.  The following chart shows
the translation of the low order bit.  Other bits are the same.
========================= Low order bit ==========================
                    | REDUNDANT | COMPACT | COMPRESSED | DYNAMIC
dict_table_t::flags |     0     |    1    |     1      |    1
fil_space_t::flags  |     0     |    0    |     1      |    1
==================================================================
@return	tablespace flags (fil_space_t::flags) */
UNIV_INLINE
ulint
dict_tf_to_fsp_flags(
/*=================*/
	ulint	table_flags)	/*!< in: dict_table_t::flags */
{
	ulint fsp_flags;
914 915
	ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL(
		table_flags);
916
	ulint atomic_writes = DICT_TF_GET_ATOMIC_WRITES(table_flags);
917

918 919 920
	ut_ad((DICT_TF_GET_PAGE_COMPRESSION(table_flags) == 0)
	      == (page_compression_level == 0));

921 922 923 924 925 926 927
	DBUG_EXECUTE_IF("dict_tf_to_fsp_flags_failure",
			return(ULINT_UNDEFINED););

	/* Adjust bit zero. */
	fsp_flags = DICT_TF_HAS_ATOMIC_BLOBS(table_flags) ? 1 : 0;

	/* ZIP_SSIZE and ATOMIC_BLOBS are at the same position. */
928 929
	fsp_flags |= table_flags
		& (DICT_TF_MASK_ZIP_SSIZE | DICT_TF_MASK_ATOMIC_BLOBS);
930

931
	fsp_flags |= FSP_FLAGS_PAGE_SSIZE();
932

933 934 935
	if (page_compression_level) {
		fsp_flags |= FSP_FLAGS_MASK_PAGE_COMPRESSION;
	}
936

937
	ut_a(fsp_flags_is_valid(fsp_flags, false));
938

939 940 941
	if (DICT_TF_HAS_DATA_DIR(table_flags)) {
		fsp_flags |= 1U << FSP_FLAGS_MEM_DATA_DIR;
	}
942

943 944
	fsp_flags |= atomic_writes << FSP_FLAGS_MEM_ATOMIC_WRITES;
	fsp_flags |= page_compression_level << FSP_FLAGS_MEM_COMPRESSION_LEVEL;
945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971

	return(fsp_flags);
}

/********************************************************************//**
Convert a 32 bit integer from SYS_TABLES.TYPE to dict_table_t::flags
The following chart shows the translation of the low order bit.
Other bits are the same.
========================= Low order bit ==========================
                    | REDUNDANT | COMPACT | COMPRESSED and DYNAMIC
SYS_TABLES.TYPE     |     1     |    1    |     1
dict_table_t::flags |     0     |    1    |     1
==================================================================
@return	ulint containing SYS_TABLES.TYPE */
UNIV_INLINE
ulint
dict_sys_tables_type_to_tf(
/*=======================*/
	ulint	type,	/*!< in: SYS_TABLES.TYPE field */
	ulint	n_cols)	/*!< in: SYS_TABLES.N_COLS field */
{
	ulint	flags;
	ulint	redundant = !(n_cols & DICT_N_COLS_COMPACT);

	/* Adjust bit zero. */
	flags = redundant ? 0 : 1;

972 973
	/* ZIP_SSIZE, ATOMIC_BLOBS, DATA_DIR, PAGE_COMPRESSION,
	PAGE_COMPRESSION_LEVEL, ATOMIC_WRITES are the same. */
974 975
	flags |= type & (DICT_TF_MASK_ZIP_SSIZE
			 | DICT_TF_MASK_ATOMIC_BLOBS
976 977 978 979
			 | DICT_TF_MASK_DATA_DIR
			 | DICT_TF_MASK_PAGE_COMPRESSION
			 | DICT_TF_MASK_PAGE_COMPRESSION_LEVEL
			 | DICT_TF_MASK_ATOMIC_WRITES
Monty's avatar
Monty committed
980

981
	);
982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008

	return(flags);
}

/********************************************************************//**
Convert a 32 bit integer table flags to the 32bit integer that is written
to a SYS_TABLES.TYPE field. The following chart shows the translation of
the low order bit.  Other bits are the same.
========================= Low order bit ==========================
                    | REDUNDANT | COMPACT | COMPRESSED and DYNAMIC
dict_table_t::flags |     0     |    1    |     1
SYS_TABLES.TYPE     |     1     |    1    |     1
==================================================================
@return	ulint containing SYS_TABLES.TYPE */
UNIV_INLINE
ulint
dict_tf_to_sys_tables_type(
/*=======================*/
	ulint	flags)	/*!< in: dict_table_t::flags */
{
	ulint type;

	ut_a(dict_tf_is_valid(flags));

	/* Adjust bit zero. It is always 1 in SYS_TABLES.TYPE */
	type = 1;

1009 1010
	/* ZIP_SSIZE, ATOMIC_BLOBS, DATA_DIR, PAGE_COMPRESSION,
	PAGE_COMPRESSION_LEVEL, ATOMIC_WRITES are the same. */
1011 1012
	type |= flags & (DICT_TF_MASK_ZIP_SSIZE
			 | DICT_TF_MASK_ATOMIC_BLOBS
1013 1014 1015
			 | DICT_TF_MASK_DATA_DIR
			 | DICT_TF_MASK_PAGE_COMPRESSION
			 | DICT_TF_MASK_PAGE_COMPRESSION_LEVEL
1016
			 | DICT_TF_MASK_ATOMIC_WRITES);
1017 1018 1019 1020 1021 1022 1023

	return(type);
}

/********************************************************************//**
Extract the compressed page size from dict_table_t::flags.
These flags are in memory, so assert that they are valid.
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1024
@return	compressed page size, or 0 if not compressed */
1025 1026
UNIV_INLINE
ulint
1027 1028
dict_tf_get_zip_size(
/*=================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1029
	ulint	flags)	/*!< in: flags */
1030
{
1031 1032 1033 1034
	ulint zip_ssize = DICT_TF_GET_ZIP_SSIZE(flags);
	ulint zip_size = (zip_ssize
			  ? (UNIV_ZIP_SIZE_MIN >> 1) << zip_ssize
			  : 0);
1035

1036
	ut_ad(zip_size <= UNIV_ZIP_SIZE_MAX);
1037 1038 1039 1040

	return(zip_size);
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1041 1042 1043
/********************************************************************//**
Check whether the table uses the compressed compact page format.
@return	compressed page size, or 0 if not compressed */
1044 1045 1046 1047
UNIV_INLINE
ulint
dict_table_zip_size(
/*================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1048
	const dict_table_t*	table)	/*!< in: table */
1049 1050 1051
{
	ut_ad(table);

1052
	return(dict_tf_get_zip_size(table->flags));
1053 1054
}

1055
#ifndef UNIV_HOTBACKUP
1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097
/*********************************************************************//**
Obtain exclusive locks on all index trees of the table. This is to prevent
accessing index trees while InnoDB is updating internal metadata for
operations such as truncate tables. */
UNIV_INLINE
void
dict_table_x_lock_indexes(
/*======================*/
	dict_table_t*	table)	/*!< in: table */
{
	dict_index_t*   index;

	ut_a(table);
	ut_ad(mutex_own(&(dict_sys->mutex)));

	/* Loop through each index of the table and lock them */
	for (index = dict_table_get_first_index(table);
	     index != NULL;
	     index = dict_table_get_next_index(index)) {
		rw_lock_x_lock(dict_index_get_lock(index));
	}
}

/*********************************************************************//**
Release the exclusive locks on all index tree. */
UNIV_INLINE
void
dict_table_x_unlock_indexes(
/*========================*/
	dict_table_t*	table)	/*!< in: table */
{
	dict_index_t*   index;

	ut_a(table);
	ut_ad(mutex_own(&(dict_sys->mutex)));

	for (index = dict_table_get_first_index(table);
	     index != NULL;
	     index = dict_table_get_next_index(index)) {
		rw_lock_x_unlock(dict_index_get_lock(index));
	}
}
1098
#endif /* !UNIV_HOTBACKUP */
1099

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1100
/********************************************************************//**
1101
Gets the number of fields in the internal representation of an index,
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1102 1103
including fields added by the dictionary system.
@return	number of fields */
1104 1105 1106 1107
UNIV_INLINE
ulint
dict_index_get_n_fields(
/*====================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1108
	const dict_index_t*	index)	/*!< in: an internal
1109 1110 1111 1112 1113 1114 1115 1116 1117
					representation of index (in
					the dictionary cache) */
{
	ut_ad(index);
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);

	return(index->n_fields);
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1118
/********************************************************************//**
1119 1120 1121
Gets the number of fields in the internal representation of an index
that uniquely determine the position of an index entry in the index, if
we do not take multiversioning into account: in the B-tree use the value
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1122 1123
returned by dict_index_get_n_unique_in_tree.
@return	number of fields */
1124 1125 1126 1127
UNIV_INLINE
ulint
dict_index_get_n_unique(
/*====================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1128
	const dict_index_t*	index)	/*!< in: an internal representation
1129 1130 1131 1132 1133 1134 1135 1136 1137
					of index (in the dictionary cache) */
{
	ut_ad(index);
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
	ut_ad(index->cached);

	return(index->n_uniq);
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1138
/********************************************************************//**
1139 1140
Gets the number of fields in the internal representation of an index
which uniquely determine the position of an index entry in the index, if
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1141 1142
we also take multiversioning into account.
@return	number of fields */
1143 1144 1145 1146
UNIV_INLINE
ulint
dict_index_get_n_unique_in_tree(
/*============================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1147
	const dict_index_t*	index)	/*!< in: an internal representation
1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161
					of index (in the dictionary cache) */
{
	ut_ad(index);
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
	ut_ad(index->cached);

	if (dict_index_is_clust(index)) {

		return(dict_index_get_n_unique(index));
	}

	return(dict_index_get_n_fields(index));
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1162
/********************************************************************//**
1163 1164 1165
Gets the number of user-defined ordering fields in the index. In the internal
representation of clustered indexes we add the row id to the ordering fields
to make a clustered index unique, but this function returns the number of
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1166 1167
fields the user defined in the index as ordering fields.
@return	number of fields */
1168 1169 1170 1171
UNIV_INLINE
ulint
dict_index_get_n_ordering_defined_by_user(
/*======================================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1172
	const dict_index_t*	index)	/*!< in: an internal representation
1173 1174 1175 1176 1177 1178
					of index (in the dictionary cache) */
{
	return(index->n_user_defined_cols);
}

#ifdef UNIV_DEBUG
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1179 1180 1181
/********************************************************************//**
Gets the nth field of an index.
@return	pointer to field object */
1182 1183 1184 1185
UNIV_INLINE
dict_field_t*
dict_index_get_nth_field(
/*=====================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1186 1187
	const dict_index_t*	index,	/*!< in: index */
	ulint			pos)	/*!< in: position of field */
1188 1189 1190 1191 1192 1193 1194 1195 1196
{
	ut_ad(index);
	ut_ad(pos < index->n_def);
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);

	return((dict_field_t*) (index->fields) + pos);
}
#endif /* UNIV_DEBUG */

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1197 1198 1199
/********************************************************************//**
Returns the position of a system column in an index.
@return	position, ULINT_UNDEFINED if not contained */
1200 1201 1202 1203
UNIV_INLINE
ulint
dict_index_get_sys_col_pos(
/*=======================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1204 1205
	const dict_index_t*	index,	/*!< in: index */
	ulint			type)	/*!< in: DATA_ROW_ID, ... */
1206 1207 1208
{
	ut_ad(index);
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
1209
	ut_ad(!dict_index_is_univ(index));
1210 1211 1212 1213 1214 1215 1216 1217 1218

	if (dict_index_is_clust(index)) {

		return(dict_col_get_clust_pos(
			       dict_table_get_sys_col(index->table, type),
			       index));
	}

	return(dict_index_get_nth_col_pos(
1219 1220
			index, dict_table_get_sys_col_no(index->table, type),
			NULL));
1221 1222
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1223 1224 1225
/*********************************************************************//**
Gets the field column.
@return	field->col, pointer to the table column */
1226 1227 1228 1229
UNIV_INLINE
const dict_col_t*
dict_field_get_col(
/*===============*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1230
	const dict_field_t*	field)	/*!< in: index field */
1231 1232 1233 1234 1235 1236
{
	ut_ad(field);

	return(field->col);
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1237 1238 1239
/********************************************************************//**
Gets pointer to the nth column in an index.
@return	column */
1240 1241 1242 1243
UNIV_INLINE
const dict_col_t*
dict_index_get_nth_col(
/*===================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1244 1245
	const dict_index_t*	index,	/*!< in: index */
	ulint			pos)	/*!< in: position of the field */
1246 1247 1248 1249
{
	return(dict_field_get_col(dict_index_get_nth_field(index, pos)));
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1250 1251 1252
/********************************************************************//**
Gets the column number the nth field in an index.
@return	column number */
1253 1254 1255 1256
UNIV_INLINE
ulint
dict_index_get_nth_col_no(
/*======================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1257 1258
	const dict_index_t*	index,	/*!< in: index */
	ulint			pos)	/*!< in: position of the field */
1259 1260 1261 1262
{
	return(dict_col_get_no(dict_index_get_nth_col(index, pos)));
}

1263 1264 1265 1266 1267 1268 1269 1270 1271
/********************************************************************//**
Looks for column n in an index.
@return position in internal representation of the index;
ULINT_UNDEFINED if not contained */
UNIV_INLINE
ulint
dict_index_get_nth_col_pos(
/*=======================*/
	const dict_index_t*	index,	/*!< in: index */
1272 1273
	ulint			n,	/*!< in: column number */
	ulint*			prefix_col_pos) /*!< out: col num if prefix */
1274
{
1275 1276
	return(dict_index_get_nth_col_or_prefix_pos(index, n, FALSE,
						    prefix_col_pos));
1277 1278
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1279 1280 1281 1282
#ifndef UNIV_HOTBACKUP
/********************************************************************//**
Returns the minimum data size of an index record.
@return	minimum data size in bytes */
1283 1284 1285 1286
UNIV_INLINE
ulint
dict_index_get_min_size(
/*====================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1287
	const dict_index_t*	index)	/*!< in: index */
1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299
{
	ulint	n	= dict_index_get_n_fields(index);
	ulint	size	= 0;

	while (n--) {
		size += dict_col_get_min_size(dict_index_get_nth_col(index,
								     n));
	}

	return(size);
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1300 1301 1302
/*********************************************************************//**
Gets the space id of the root of the index tree.
@return	space id */
1303 1304 1305 1306
UNIV_INLINE
ulint
dict_index_get_space(
/*=================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1307
	const dict_index_t*	index)	/*!< in: index */
1308 1309 1310 1311 1312 1313 1314
{
	ut_ad(index);
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);

	return(index->space);
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1315
/*********************************************************************//**
1316 1317 1318 1319 1320
Sets the space id of the root of the index tree. */
UNIV_INLINE
void
dict_index_set_space(
/*=================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1321 1322
	dict_index_t*	index,	/*!< in/out: index */
	ulint		space)	/*!< in: space id */
1323 1324 1325 1326 1327 1328 1329
{
	ut_ad(index);
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);

	index->space = space;
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1330 1331 1332
/*********************************************************************//**
Gets the page number of the root of the index tree.
@return	page number */
1333 1334 1335 1336
UNIV_INLINE
ulint
dict_index_get_page(
/*================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1337
	const dict_index_t*	index)	/*!< in: index */
1338 1339 1340 1341 1342 1343 1344
{
	ut_ad(index);
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);

	return(index->page);
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1345 1346 1347
/*********************************************************************//**
Gets the read-write lock of the index tree.
@return	read-write lock */
1348
UNIV_INLINE
1349
prio_rw_lock_t*
1350 1351
dict_index_get_lock(
/*================*/
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1352
	dict_index_t*	index)	/*!< in: index */
1353 1354 1355 1356 1357 1358 1359
{
	ut_ad(index);
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);

	return(&(index->lock));
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1360
/********************************************************************//**
1361 1362
Returns free space reserved for future updates of records. This is
relevant only in the case of many consecutive inserts, as updates
Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1363 1364
which make the records bigger might fragment the index.
@return	number of free bytes on page, reserved for updates */
1365 1366 1367 1368 1369 1370 1371 1372
UNIV_INLINE
ulint
dict_index_get_space_reserve(void)
/*==============================*/
{
	return(UNIV_PAGE_SIZE / 16);
}

1373 1374 1375
/********************************************************************//**
Gets the status of online index creation.
@return the status */
1376
UNIV_INLINE
1377 1378 1379 1380
enum online_index_status
dict_index_get_online_status(
/*=========================*/
	const dict_index_t*	index)	/*!< in: secondary index */
1381
{
1382
	enum online_index_status	status;
1383

1384
	status = (enum online_index_status) index->online_status;
1385

1386 1387 1388 1389 1390 1391
	/* Without the index->lock protection, the online
	status can change from ONLINE_INDEX_CREATION to
	ONLINE_INDEX_COMPLETE (or ONLINE_INDEX_ABORTED) in
	row_log_apply() once log application is done. So to make
	sure the status is ONLINE_INDEX_CREATION or ONLINE_INDEX_COMPLETE
	you should always do the recheck after acquiring index->lock */
Vadim Tkachenko's avatar
Vadim Tkachenko committed
1392

1393 1394 1395 1396 1397 1398 1399
#ifdef UNIV_DEBUG
	switch (status) {
	case ONLINE_INDEX_COMPLETE:
	case ONLINE_INDEX_CREATION:
	case ONLINE_INDEX_ABORTED:
	case ONLINE_INDEX_ABORTED_DROPPED:
		return(status);
Vadim Tkachenko's avatar
Vadim Tkachenko committed
1400
	}
1401 1402 1403
	ut_error;
#endif /* UNIV_DEBUG */
	return(status);
1404 1405
}

1406 1407
/********************************************************************//**
Sets the status of online index creation. */
1408
UNIV_INLINE
1409 1410 1411 1412 1413
void
dict_index_set_online_status(
/*=========================*/
	dict_index_t*			index,	/*!< in/out: index */
	enum online_index_status	status)	/*!< in: status */
1414
{
1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430
	ut_ad(!(index->type & DICT_FTS));
#ifdef UNIV_SYNC_DEBUG
	ut_ad(rw_lock_own(dict_index_get_lock(index), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
#ifdef UNIV_DEBUG
	switch (dict_index_get_online_status(index)) {
	case ONLINE_INDEX_COMPLETE:
	case ONLINE_INDEX_CREATION:
		break;
	case ONLINE_INDEX_ABORTED:
		ut_ad(status == ONLINE_INDEX_ABORTED_DROPPED);
		break;
	case ONLINE_INDEX_ABORTED_DROPPED:
		ut_error;
	}
#endif /* UNIV_DEBUG */
1431

1432 1433 1434
	index->online_status = status;
	ut_ad(dict_index_get_online_status(index) == status);
}
1435

1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459
/********************************************************************//**
Determines if a secondary index is being or has been created online,
or if the table is being rebuilt online, allowing concurrent modifications
to the table.
@retval true if the index is being or has been built online, or
if this is a clustered index and the table is being or has been rebuilt online
@retval false if the index has been created or the table has been
rebuilt completely */
UNIV_INLINE
bool
dict_index_is_online_ddl(
/*=====================*/
	const dict_index_t*	index)	/*!< in: index */
{
#ifdef UNIV_DEBUG
	if (dict_index_is_clust(index)) {
		switch (dict_index_get_online_status(index)) {
		case ONLINE_INDEX_CREATION:
			return(true);
		case ONLINE_INDEX_COMPLETE:
			return(false);
		case ONLINE_INDEX_ABORTED:
		case ONLINE_INDEX_ABORTED_DROPPED:
			break;
1460
		}
1461 1462
		ut_ad(0);
		return(false);
1463
	}
1464
#endif /* UNIV_DEBUG */
1465

1466 1467
	return(UNIV_UNLIKELY(dict_index_get_online_status(index)
			     != ONLINE_INDEX_COMPLETE));
1468 1469
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1470
/**********************************************************************//**
1471 1472
Check whether a column exists in an FTS index.
@return ULINT_UNDEFINED if no match else the offset within the vector */
1473
UNIV_INLINE
1474 1475
ulint
dict_table_is_fts_column(
1476
/*=====================*/
1477 1478 1479
	ib_vector_t*	indexes,/*!< in: vector containing only FTS indexes */
	ulint		col_no)	/*!< in: col number to search for */

1480
{
1481
	ulint		i;
1482

1483 1484
	for (i = 0; i < ib_vector_size(indexes); ++i) {
		dict_index_t*	index;
1485

1486
		index = (dict_index_t*) ib_vector_getp(indexes, i);
1487

1488
		if (dict_index_contains_col_or_prefix(index, col_no)) {
1489

1490 1491
			return(i);
		}
Vadim Tkachenko's avatar
Vadim Tkachenko committed
1492 1493
	}

1494
	return(ULINT_UNDEFINED);
1495
}
1496 1497 1498

/**********************************************************************//**
Determine bytes of column prefix to be stored in the undo log. Please
1499
note if the table format is UNIV_FORMAT_A (< UNIV_FORMAT_B), no prefix
1500 1501 1502 1503 1504 1505 1506 1507 1508 1509
needs to be stored in the undo log.
@return bytes of column prefix to be stored in the undo log */
UNIV_INLINE
ulint
dict_max_field_len_store_undo(
/*==========================*/
	dict_table_t*		table,	/*!< in: table */
	const dict_col_t*	col)	/*!< in: column which index prefix
					is based on */
{
1510
	ulint	prefix_len = 0;
1511

1512
	if (dict_table_get_format(table) >= UNIV_FORMAT_B)
1513 1514 1515 1516 1517 1518 1519 1520 1521
	{
		prefix_len = col->max_prefix
			? col->max_prefix
			: DICT_MAX_FIELD_LEN_BY_FORMAT(table);
	}

	return(prefix_len);
}

1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532
/********************************************************************//**
Check whether the index is corrupted.
@return	nonzero for corrupted index, zero for valid indexes */
UNIV_INLINE
ulint
dict_index_is_corrupted(
/*====================*/
	const dict_index_t*	index)	/*!< in: index */
{
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);

1533
	return((index->type & DICT_CORRUPT)
1534
	        || (index->table && index->table->corrupted));
1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558
}

/********************************************************************//**
Check if the tablespace for the table has been discarded.
@return	true if the tablespace has been discarded. */
UNIV_INLINE
bool
dict_table_is_discarded(
/*====================*/
	const dict_table_t*	table)	/*!< in: table to check */
{
	return(DICT_TF2_FLAG_IS_SET(table, DICT_TF2_DISCARDED));
}

/********************************************************************//**
Check if it is a temporary table.
@return	true if temporary table flag is set. */
UNIV_INLINE
bool
dict_table_is_temporary(
/*====================*/
	const dict_table_t*	table)	/*!< in: table to check */
{
	return(DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY));
1559 1560
}

1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587
/**********************************************************************//**
Get index by first field of the index
@return index which is having first field matches
with the field present in field_index position of table */
UNIV_INLINE
dict_index_t*
dict_table_get_index_on_first_col(
/*==============================*/
	const dict_table_t*	table,		/*!< in: table */
	ulint			col_index)	/*!< in: position of column
						in table */
{
	ut_ad(col_index < table->n_cols);

	dict_col_t* column = dict_table_get_nth_col(table, col_index);

	for (dict_index_t* index = dict_table_get_first_index(table);
		index != NULL; index = dict_table_get_next_index(index)) {

		if (index->fields[0].col == column) {
			return(index);
		}
	}
	ut_error;
	return(0);
}

Aleksandr Kuzminsky's avatar
Aleksandr Kuzminsky committed
1588
#endif /* !UNIV_HOTBACKUP */