Commit 6b71b3e3 authored by Marko Mäkelä's avatar Marko Mäkelä

Follow-up to MDEV-12873: Refactor SYS_TABLES.TYPE validation

dict_sys_tables_type_to_tf(): Change the parameter n_cols to not_redundant.

dict_tf_is_valid_not_redundant(): Refactored from dict_tf_is_valid().

dict_sys_tables_type_valid(): Replaces dict_sys_tables_type_validate().
Use the common function dict_tf_is_valid_not_redundant(), which validates
PAGE_COMPRESSION_LEVEL more strictly.

DICT_TF_GET_UNUSED(flags): Remove.
parent 615b1f41
......@@ -1129,6 +1129,71 @@ dict_sys_tablespaces_rec_read(
return(true);
}
/** Check if SYS_TABLES.TYPE is valid
@param[in] type SYS_TABLES.TYPE
@param[in] not_redundant whether ROW_FORMAT=REDUNDANT is not used
@return whether the SYS_TABLES.TYPE value is valid */
static
bool
dict_sys_tables_type_valid(ulint type, bool not_redundant)
{
/* The DATA_DIRECTORY flag can be assigned fully independently
of all other persistent table flags. */
type &= ~DICT_TF_MASK_DATA_DIR;
if (type == 1) {
return(true); /* ROW_FORMAT=REDUNDANT or ROW_FORMAT=COMPACT */
}
if (!(type & 1)) {
/* For ROW_FORMAT=REDUNDANT and ROW_FORMAT=COMPACT,
SYS_TABLES.TYPE=1. Else, it is the same as
dict_table_t::flags, and the least significant bit
would be set. So, the bit never can be 0. */
return(false);
}
if (!not_redundant) {
/* SYS_TABLES.TYPE must be 1 for ROW_FORMAT=REDUNDANT. */
return(false);
}
if (type >= 1U << DICT_TF_POS_UNUSED) {
/* Some unknown bits are set. */
return(false);
}
/* ATOMIC_WRITES cannot be 3; it is the 10.3 NO_ROLLBACK flag. */
if (!(~type & DICT_TF_MASK_ATOMIC_WRITES)) {
return(false);
}
return(dict_tf_is_valid_not_redundant(type));
}
/** Convert SYS_TABLES.TYPE to dict_table_t::flags.
@param[in] type SYS_TABLES.TYPE
@param[in] not_redundant whether ROW_FORMAT=REDUNDANT is not used
@return table flags */
static
ulint
dict_sys_tables_type_to_tf(ulint type, bool not_redundant)
{
ut_ad(dict_sys_tables_type_valid(type, not_redundant));
ulint flags = not_redundant ? 1 : 0;
/* ZIP_SSIZE, ATOMIC_BLOBS, DATA_DIR, PAGE_COMPRESSION,
PAGE_COMPRESSION_LEVEL are the same. */
flags |= type & (DICT_TF_MASK_ZIP_SSIZE
| DICT_TF_MASK_ATOMIC_BLOBS
| DICT_TF_MASK_DATA_DIR
| DICT_TF_MASK_PAGE_COMPRESSION
| DICT_TF_MASK_PAGE_COMPRESSION_LEVEL);
ut_ad(dict_tf_is_valid(flags));
return(flags);
}
/** Read and return 5 integer fields from a SYS_TABLES record.
@param[in] rec A record of SYS_TABLES
@param[in] name Table Name, the same as SYS_TABLES.NAME
......@@ -1222,8 +1287,7 @@ dict_sys_tables_rec_read(
SYS_TABLES.TYPE to be in the 10.2.2..10.2.6 format.
This would in any case be invalid format for 10.2 and
earlier releases. */
ut_ad(ULINT_UNDEFINED == dict_sys_tables_type_validate(
type, DICT_N_COLS_COMPACT));
ut_ad(!dict_sys_tables_type_valid(type, true));
} else {
/* SYS_TABLES.TYPE is of the form AALLLL10DB00001. We
must still validate that the LLLL bits are between 0
......@@ -1239,8 +1303,7 @@ dict_sys_tables_rec_read(
ut_ad(DICT_TF_GET_PAGE_COMPRESSION_LEVEL(type) >= 1);
ut_ad(DICT_TF_GET_PAGE_COMPRESSION_LEVEL(type) <= 9);
} else {
ut_ad(ULINT_UNDEFINED == dict_sys_tables_type_validate(
type, DICT_N_COLS_COMPACT));
ut_ad(!dict_sys_tables_type_valid(type, true));
}
}
......@@ -1255,11 +1318,9 @@ dict_sys_tables_rec_read(
ut_a(len == 4);
*n_cols = mach_read_from_4(field);
/* This validation function also combines the DICT_N_COLS_COMPACT
flag in n_cols into the type field to effectively make it a
dict_table_t::flags. */
const bool not_redundant = 0 != (*n_cols & DICT_N_COLS_COMPACT);
if (ULINT_UNDEFINED == dict_sys_tables_type_validate(type, *n_cols)) {
if (!dict_sys_tables_type_valid(type, not_redundant)) {
ib::error() << "Table " << table_name << " in InnoDB"
" data dictionary contains invalid flags."
" SYS_TABLES.TYPE=" << type <<
......@@ -1267,7 +1328,7 @@ dict_sys_tables_rec_read(
return(false);
}
*flags = dict_sys_tables_type_to_tf(type, *n_cols);
*flags = dict_sys_tables_type_to_tf(type, not_redundant);
/* For tables created before MySQL 4.1, there may be
garbage in SYS_TABLES.MIX_LEN where flags2 are found. Such tables
......@@ -1275,7 +1336,7 @@ dict_sys_tables_rec_read(
high bit set in n_cols, and flags would be zero.
MySQL 4.1 was the first version to support innodb_file_per_table,
that is, *space_id != 0. */
if (*flags != 0 || *space_id != 0 || *n_cols & DICT_N_COLS_COMPACT) {
if (not_redundant || *space_id != 0 || *n_cols & DICT_N_COLS_COMPACT) {
/* Get flags2 from SYS_TABLES.MIX_LEN */
field = rec_get_nth_field_old(
......
......@@ -638,31 +638,15 @@ dict_table_has_fts_index(
return(DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS));
}
/** Validate the table flags.
@param[in] flags Table flags
@return true if valid. */
UNIV_INLINE
/** Validate the flags for tables that are not ROW_FORMAT=REDUNDANT.
@param[in] flags table flags
@return whether the flags are valid */
inline
bool
dict_tf_is_valid(
ulint flags)
dict_tf_is_valid_not_redundant(ulint flags)
{
/* Make sure there are no bits that we do not know about. */
if (flags >= 1U << DICT_TF_BITS) {
return(false);
}
const bool not_redundant = DICT_TF_GET_COMPACT(flags);
const bool atomic_blobs = DICT_TF_HAS_ATOMIC_BLOBS(flags);
if (atomic_blobs && !not_redundant) {
/* ROW_FORMAT=COMPRESSED and ROW_FORMAT=DYNAMIC both use
atomic_blobs, which build on the page structure introduced
for ROW_FORMAT=COMPACT by allowing keys in secondary
indexes to be made from data stored off-page in the
clustered index. */
return(false);
}
ulint zip_ssize = DICT_TF_GET_ZIP_SSIZE(flags);
if (!zip_ssize) {
......@@ -689,14 +673,36 @@ dict_tf_is_valid(
ROW_FORMAT=COMPACT or ROW_FORMAT=DYNAMIC
(not ROW_FORMAT=COMPRESSED or ROW_FORMAT=REDUNDANT)
and PAGE_COMPRESSED=YES */
return(!zip_ssize && not_redundant
&& DICT_TF_GET_PAGE_COMPRESSION(flags));
return(!zip_ssize && DICT_TF_GET_PAGE_COMPRESSION(flags));
default:
/* Invalid PAGE_COMPRESSION_LEVEL value */
return(false);
}
}
/** Validate the table flags.
@param[in] flags Table flags
@return true if valid. */
UNIV_INLINE
bool
dict_tf_is_valid(
ulint flags)
{
ut_ad(flags < 1U << DICT_TF_BITS);
/* The DATA_DIRECTORY flag can be assigned fully independently
of all other persistent table flags. */
flags &= ~DICT_TF_MASK_DATA_DIR;
if (!(flags & 1)) {
/* Only ROW_FORMAT=REDUNDANT has 0 in the least significant
bit. For ROW_FORMAT=REDUNDANT, only the DATA_DIR flag
(which we cleared above) can be set. If any other flags
are set, the flags are invalid. */
return(flags == 0);
}
return(dict_tf_is_valid_not_redundant(flags));
}
/** Validate both table flags and table flags2 and make sure they
are compatible.
@param[in] flags Table flags
......@@ -719,96 +725,6 @@ dict_tf2_is_valid(
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);
bool page_compression = DICT_TF_GET_PAGE_COMPRESSION(type);
ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL(type);
/* 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. */
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);
}
}
/* Validate that the atomic writes number is within allowed range. */
if (DICT_TF_GET_ATOMIC_WRITES(type) == 3) {
return(ULINT_UNDEFINED);
}
/* 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
......@@ -973,41 +889,6 @@ dict_tf_to_fsp_flags(ulint table_flags)
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;
/* ZIP_SSIZE, ATOMIC_BLOBS, DATA_DIR, PAGE_COMPRESSION,
PAGE_COMPRESSION_LEVEL are the same. */
flags |= type & (DICT_TF_MASK_ZIP_SSIZE
| DICT_TF_MASK_ATOMIC_BLOBS
| DICT_TF_MASK_DATA_DIR
| DICT_TF_MASK_PAGE_COMPRESSION
| DICT_TF_MASK_PAGE_COMPRESSION_LEVEL);
ut_ad(!DICT_TF_GET_ZIP_SSIZE(flags) || DICT_TF_HAS_ATOMIC_BLOBS(flags));
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
......
......@@ -238,9 +238,6 @@ DEFAULT=0, ON = 1, OFF = 2
((flags & DICT_TF_MASK_ATOMIC_WRITES) \
>> DICT_TF_POS_ATOMIC_WRITES)
/** Return the contents of the UNUSED bits */
#define DICT_TF_GET_UNUSED(flags) \
(flags >> DICT_TF_POS_UNUSED)
/* @} */
/** @brief Table Flags set number 2.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment