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( ...@@ -1129,6 +1129,71 @@ dict_sys_tablespaces_rec_read(
return(true); 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. /** Read and return 5 integer fields from a SYS_TABLES record.
@param[in] rec A record of SYS_TABLES @param[in] rec A record of SYS_TABLES
@param[in] name Table Name, the same as SYS_TABLES.NAME @param[in] name Table Name, the same as SYS_TABLES.NAME
...@@ -1222,8 +1287,7 @@ dict_sys_tables_rec_read( ...@@ -1222,8 +1287,7 @@ dict_sys_tables_rec_read(
SYS_TABLES.TYPE to be in the 10.2.2..10.2.6 format. 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 This would in any case be invalid format for 10.2 and
earlier releases. */ earlier releases. */
ut_ad(ULINT_UNDEFINED == dict_sys_tables_type_validate( ut_ad(!dict_sys_tables_type_valid(type, true));
type, DICT_N_COLS_COMPACT));
} else { } else {
/* SYS_TABLES.TYPE is of the form AALLLL10DB00001. We /* SYS_TABLES.TYPE is of the form AALLLL10DB00001. We
must still validate that the LLLL bits are between 0 must still validate that the LLLL bits are between 0
...@@ -1239,8 +1303,7 @@ dict_sys_tables_rec_read( ...@@ -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) >= 1);
ut_ad(DICT_TF_GET_PAGE_COMPRESSION_LEVEL(type) <= 9); ut_ad(DICT_TF_GET_PAGE_COMPRESSION_LEVEL(type) <= 9);
} else { } else {
ut_ad(ULINT_UNDEFINED == dict_sys_tables_type_validate( ut_ad(!dict_sys_tables_type_valid(type, true));
type, DICT_N_COLS_COMPACT));
} }
} }
...@@ -1255,11 +1318,9 @@ dict_sys_tables_rec_read( ...@@ -1255,11 +1318,9 @@ dict_sys_tables_rec_read(
ut_a(len == 4); ut_a(len == 4);
*n_cols = mach_read_from_4(field); *n_cols = mach_read_from_4(field);
/* This validation function also combines the DICT_N_COLS_COMPACT const bool not_redundant = 0 != (*n_cols & DICT_N_COLS_COMPACT);
flag in n_cols into the type field to effectively make it a
dict_table_t::flags. */
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" ib::error() << "Table " << table_name << " in InnoDB"
" data dictionary contains invalid flags." " data dictionary contains invalid flags."
" SYS_TABLES.TYPE=" << type << " SYS_TABLES.TYPE=" << type <<
...@@ -1267,7 +1328,7 @@ dict_sys_tables_rec_read( ...@@ -1267,7 +1328,7 @@ dict_sys_tables_rec_read(
return(false); 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 /* For tables created before MySQL 4.1, there may be
garbage in SYS_TABLES.MIX_LEN where flags2 are found. Such tables garbage in SYS_TABLES.MIX_LEN where flags2 are found. Such tables
...@@ -1275,7 +1336,7 @@ dict_sys_tables_rec_read( ...@@ -1275,7 +1336,7 @@ dict_sys_tables_rec_read(
high bit set in n_cols, and flags would be zero. high bit set in n_cols, and flags would be zero.
MySQL 4.1 was the first version to support innodb_file_per_table, MySQL 4.1 was the first version to support innodb_file_per_table,
that is, *space_id != 0. */ 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 */ /* Get flags2 from SYS_TABLES.MIX_LEN */
field = rec_get_nth_field_old( field = rec_get_nth_field_old(
......
...@@ -638,31 +638,15 @@ dict_table_has_fts_index( ...@@ -638,31 +638,15 @@ dict_table_has_fts_index(
return(DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS)); return(DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS));
} }
/** Validate the table flags. /** Validate the flags for tables that are not ROW_FORMAT=REDUNDANT.
@param[in] flags Table flags @param[in] flags table flags
@return true if valid. */ @return whether the flags are valid */
UNIV_INLINE inline
bool bool
dict_tf_is_valid( dict_tf_is_valid_not_redundant(ulint flags)
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); 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); ulint zip_ssize = DICT_TF_GET_ZIP_SSIZE(flags);
if (!zip_ssize) { if (!zip_ssize) {
...@@ -689,14 +673,36 @@ dict_tf_is_valid( ...@@ -689,14 +673,36 @@ dict_tf_is_valid(
ROW_FORMAT=COMPACT or ROW_FORMAT=DYNAMIC ROW_FORMAT=COMPACT or ROW_FORMAT=DYNAMIC
(not ROW_FORMAT=COMPRESSED or ROW_FORMAT=REDUNDANT) (not ROW_FORMAT=COMPRESSED or ROW_FORMAT=REDUNDANT)
and PAGE_COMPRESSED=YES */ and PAGE_COMPRESSED=YES */
return(!zip_ssize && not_redundant return(!zip_ssize && DICT_TF_GET_PAGE_COMPRESSION(flags));
&& DICT_TF_GET_PAGE_COMPRESSION(flags));
default: default:
/* Invalid PAGE_COMPRESSION_LEVEL value */ /* Invalid PAGE_COMPRESSION_LEVEL value */
return(false); 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 /** Validate both table flags and table flags2 and make sure they
are compatible. are compatible.
@param[in] flags Table flags @param[in] flags Table flags
...@@ -719,96 +725,6 @@ dict_tf2_is_valid( ...@@ -719,96 +725,6 @@ dict_tf2_is_valid(
return(true); 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 Determine the file format from dict_table_t::flags
The low order bit will be zero for REDUNDANT and 1 for COMPACT. For any 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) ...@@ -973,41 +889,6 @@ dict_tf_to_fsp_flags(ulint table_flags)
return(fsp_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 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 to a SYS_TABLES.TYPE field. The following chart shows the translation of
......
...@@ -238,9 +238,6 @@ DEFAULT=0, ON = 1, OFF = 2 ...@@ -238,9 +238,6 @@ DEFAULT=0, ON = 1, OFF = 2
((flags & DICT_TF_MASK_ATOMIC_WRITES) \ ((flags & DICT_TF_MASK_ATOMIC_WRITES) \
>> DICT_TF_POS_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. /** @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