Skip to content

Commit

Permalink
Merge pull request #1560 from venkatesh-prasad-v/PXB-3283-trunk
Browse files Browse the repository at this point in the history
PXB-3283: Column %s precise type mismatch error while importing a tablespace (trunk)
  • Loading branch information
venkatesh-prasad-v authored May 24, 2024
2 parents db75067 + 334f593 commit 786e71a
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 11 deletions.
17 changes: 17 additions & 0 deletions storage/innobase/data/data0type.cc
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,23 @@ bool dtype_is_string_type(
return false;
}

#ifdef XTRABACKUP
/** Checks if the main data type is a real temporal type with fractional
* seconds
@param[in] type InnoDB main column type TINY, SHORT,
@return true if real temporal type */
bool dtype_is_real_temporal_type(dd::enum_column_types type) {
switch (type) {
case dd::enum_column_types::TIME2:
case dd::enum_column_types::TIMESTAMP2:
case dd::enum_column_types::DATETIME2:
return true;
default:
return false;
}
}
#endif /* XTRABACKUP */

/** Checks if a type is a binary string type. Note that for tables created with
< 4.0.14, we do not know if a DATA_BLOB column is a BLOB or a TEXT column. For
those DATA_BLOB columns this function currently returns false.
Expand Down
16 changes: 15 additions & 1 deletion storage/innobase/dict/dict0dd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -809,7 +809,21 @@ dict_table_t *dd_table_create_on_dd_obj(const dd::Table *dd_table,
charset_no = my_charset_bin.number;
else if (dd_col->type() == dd::enum_column_types::JSON)
charset_no = my_charset_utf8mb4_bin.number;
else if (dtype_is_string_type(mtype)) {
else if (dtype_is_real_temporal_type(dd_col->type())) {
/*
MySQL always stores real temporal fields in my_charset_numeric charset.
Refer to make_field() in sql/field.cc
It is for the same reason, the .cfg file exported during FLUSH TABLE
FOR EXPORT always sets prtype using my_charset_numeric as the
collation.
In order to remain consistent with server's behavior, we force temporal
datatypes to use my_charset_numeric until MySQL server provides support
for a separate charset/collation for temporal fields.
*/
charset_no = my_charset_numeric.number;
} else if (dtype_is_string_type(mtype)) {
charset_no = static_cast<ulint>(dd_col->collation_id());
}

Expand Down
28 changes: 28 additions & 0 deletions storage/innobase/include/data0type.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ this program; if not, write to the Free Software Foundation, Inc.,

#include "univ.i"

#ifdef XTRABACKUP
#include "sql/dd/types/column.h" // dd::enum_column_types

#endif /* XTRABACKUP */

extern ulint data_mysql_default_charset_coll;
constexpr uint32_t DATA_MYSQL_BINARY_CHARSET_COLL = 63;

Expand Down Expand Up @@ -315,6 +320,29 @@ ulint dtype_get_at_most_n_mbchars(
@return true if string type */
bool dtype_is_string_type(
ulint mtype); /*!< in: InnoDB main data type code: DATA_CHAR, ... */

#ifdef XTRABACKUP
/** Checks if the main data type is a real temporal type with fractional
seconds
"real type" in MySQL has different meanings in different contexts. It can mean
- a data type allowing fractional numbers for precision
- an underlying datatype used internally.
For example binlog stores CHAR, VARCHAR, SET and ENUM as MYSQL_TYPE_STRING.
For such types, field->type() will be MYSQL_TYPE_STRING and
field->real_type() will return the actual underlying data type.
However in the context of collation of temporal types, it is safe to assume
that real temporal type are the types which allow with fractional seconds
since ther are stored and displayed as DATA_FIXBINARY.
@param[in] type InnoDB main column type TINY, SHORT,
@return true if real temporal type */
bool dtype_is_real_temporal_type(dd::enum_column_types type);
#endif /* XTRABACKUP */

/** Checks if a type is a binary string type. Note that for tables created
with < 4.0.14, we do not know if a DATA_BLOB column is a BLOB or a TEXT
column. For those DATA_BLOB columns this function currently returns false.
Expand Down
2 changes: 1 addition & 1 deletion storage/innobase/xtrabackup/test/bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ main () {

TYPE="xtradb80"
PXB_TYPE="release"
VERSION="8.0.34-26"
VERSION="8.0.35-27"
DESTDIR="./server"
parse_arguments PICK-ARGS-FROM-ARGV "$@"
main
69 changes: 60 additions & 9 deletions storage/innobase/xtrabackup/test/t/xb_export.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ table_count=9
NUMBER_OF_CFG_FILES=11
if is_server_version_higher_than 8.0.28
then
NUMBER_OF_CFG_FILES=13
table_count=11
NUMBER_OF_CFG_FILES=15
table_count=13
fi

vlog "total table to test $table_count "
Expand Down Expand Up @@ -64,12 +64,28 @@ function insert_data() {
}

function create_tables() {
### check if we can import all the columns type in mysql
mysql -e 'create table test4(col1 bool, col2 int, col3 float, col4 double,
col5 timestamp, col6 long, col7 date, col8 time, col9 datetime, col10 year,
col11 varchar(20), col12 bit ,col13 decimal, col14 blob, col16 json,
col17 mediumtext, col18 enum("01","2"), col19 SET("0","1","2"),
col20 varchar(255) character set latin1 )' incremental_sample;
### check if we can import all column types in mysql
mysql -e 'create table test4(
col1 bool,
col2 int,
col3 float,
col4 double,
col5 timestamp,
col6 long,
col7 date,
col8 time,
col9 datetime,
col10 year,
col11 varchar(20),
col12 bit,
col13 decimal,
col14 blob,
col16 json,
col17 mediumtext,
col18 enum("01","2"),
col19 SET("0","1","2"),
col20 varchar(255) character set latin1
)' incremental_sample;

mysql -e 'CREATE TABLE test5(a int, b int, PRIMARY KEY (a), KEY (b DESC))' incremental_sample
mysql -e 'CREATE TABLE test6(a int)' incremental_sample
Expand All @@ -93,6 +109,14 @@ function create_tables() {
mysql -e 'ALTER TABLE test11 DROP COLUMN c3, ALGORITHM=INSTANT' incremental_sample
fi

# To verify that import tablespace is successful for tables created using
# CREATE TABLE LIKE queries
mysql -e 'CREATE TABLE test12 LIKE test4' incremental_sample

# To verify that import tablespace is successful for tables with a non
# default charset
mysql -e 'CREATE TABLE test13 LIKE test4' incremental_sample
mysql -e 'ALTER TABLE test13 CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci' incremental_sample
}


Expand Down Expand Up @@ -163,7 +187,34 @@ xtrabackup --datadir=$mysql_datadir --prepare --export \
--target-dir=$backup_dir

ls -tlr $backup_dir/incremental_sample/*cfg
cfg_count=`find $backup_dir/incremental_sample -name '*.cfg' | wc -l`
cfg_count1=`find $backup_dir/incremental_sample -name '*.cfg' | wc -l`

# Get the timestamp of the .cfg file created in the first --export
timestamp_1=$(stat -c %Y "$backup_dir/incremental_sample/test1.cfg")

# Run --prepare --export once again to verify that .cfg files are overwritten when it is run for the second time
xtrabackup --datadir=$mysql_datadir --prepare --export \
--target-dir=$backup_dir

ls -tlr $backup_dir/incremental_sample/*cfg
cfg_count2=`find $backup_dir/incremental_sample -name '*.cfg' | wc -l`

# Get the timestamp of the .cfg file created in the second --export
timestamp_2=$(stat -c %Y "$backup_dir/incremental_sample/test1.cfg")

# Compare the timestamps
if [ "$timestamp_2" -gt "$timestamp_1" ]; then
vlog "The .cfg generated by PXB in the second attempt has a newer timestamp."
else
vlog "The .cfg generated by PXB in the second attempt does not have a newer timestamp."
exit -1
fi

if [ $cfg_count1 != $cfg_count2 ]; then
vlog "Number of .cfg files created is different in the second attempt"
fi

cfg_count=$cfg_count1

vlog "Verifying .cfg files in backup, expecting ${NUMBER_OF_CFG_FILES}."
if [ $cfg_count -ne ${NUMBER_OF_CFG_FILES} ]
Expand Down

0 comments on commit 786e71a

Please sign in to comment.