From 4a58d1085dfc7e2dea7affdd7e389493fc0fd430 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Mon, 13 Jan 2025 15:40:59 +0300 Subject: [PATCH] MDEV-35612 EXCHANGE PARTITION does not work for tables with unique blobs mysql_compare_tables() failed because of no long hash index generated fields in prepared tmp_create_info. In comparison we should skip these fields in the original table by: 1. skipping INVISIBLE_SYSTEM fields; 2. getting key_info from table->s instead of table as TABLE_SHARE contains unwrapped key_info. --- mysql-test/main/partition_exchange.result | 10 ++++++++++ mysql-test/main/partition_exchange.test | 14 ++++++++++++++ sql/sql_table.cc | 22 +++++++++++++++++----- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/mysql-test/main/partition_exchange.result b/mysql-test/main/partition_exchange.result index 999517f4028..c9169c5c818 100644 --- a/mysql-test/main/partition_exchange.result +++ b/mysql-test/main/partition_exchange.result @@ -1343,3 +1343,13 @@ create or replace table t2_working like t2; alter table t2_working remove partitioning; alter table t2 exchange partition p1 with table t2_working; drop tables t1, t1_working, t2, t2_working; +# +# MDEV-35612 EXCHANGE PARTITION does not work for tables with unique blobs +# +create table t (a int, b text, unique (b), unique(a, b)) partition by list (a) (partition p0 values in (1,2), partition pdef default); +create table tp (a int, b text, c int invisible, unique (b), unique(a, b)); +alter table t exchange partition p0 with table tp; +ERROR HY000: Tables have different definitions +create or replace table tp (a int, b text, unique (b), unique(a, b)); +alter table t exchange partition p0 with table tp; +drop table t, tp; diff --git a/mysql-test/main/partition_exchange.test b/mysql-test/main/partition_exchange.test index e92b8dfff5c..767f682ea0d 100644 --- a/mysql-test/main/partition_exchange.test +++ b/mysql-test/main/partition_exchange.test @@ -586,3 +586,17 @@ alter table t2 exchange partition p1 with table t2_working; # Cleanup drop tables t1, t1_working, t2, t2_working; + +--echo # +--echo # MDEV-35612 EXCHANGE PARTITION does not work for tables with unique blobs +--echo # +create table t (a int, b text, unique (b), unique(a, b)) partition by list (a) (partition p0 values in (1,2), partition pdef default); +create table tp (a int, b text, c int invisible, unique (b), unique(a, b)); +--error ER_TABLES_DIFFERENT_METADATA +alter table t exchange partition p0 with table tp; + +create or replace table tp (a int, b text, unique (b), unique(a, b)); +alter table t exchange partition p0 with table tp; + +# cleanup +drop table t, tp; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index e744ab78a2f..3563c0fa982 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -7852,7 +7852,16 @@ bool mysql_compare_tables(TABLE *table, Alter_info *alter_info, DBUG_RETURN(1); /* Some very basic checks. */ - if (table->s->fields != alter_info->create_list.elements || + uint fields= table->s->fields; + + /* There is no field count on system-invisible fields, count them. */ + for (Field **f_ptr= table->field; *f_ptr; f_ptr++) + { + if ((*f_ptr)->invisible >= INVISIBLE_SYSTEM) + fields--; + } + + if (fields != alter_info->create_list.elements || table->s->db_type() != create_info->db_type || table->s->tmp_table || (table->s->row_type != create_info->row_type)) @@ -7863,6 +7872,9 @@ bool mysql_compare_tables(TABLE *table, Alter_info *alter_info, for (Field **f_ptr= table->field; *f_ptr; f_ptr++) { Field *field= *f_ptr; + /* Skip hidden generated field like long hash index. */ + if (field->invisible >= INVISIBLE_SYSTEM) + continue; Create_field *tmp_new_field= tmp_new_field_it++; /* Check that NULL behavior is the same. */ @@ -7915,13 +7927,13 @@ bool mysql_compare_tables(TABLE *table, Alter_info *alter_info, DBUG_RETURN(false); /* Go through keys and check if they are compatible. */ - KEY *table_key; - KEY *table_key_end= table->key_info + table->s->keys; + KEY *table_key= table->s->key_info; + KEY *table_key_end= table_key + table->s->keys; KEY *new_key; KEY *new_key_end= key_info_buffer + key_count; /* Step through all keys of the first table and search matching keys. */ - for (table_key= table->key_info; table_key < table_key_end; table_key++) + for (; table_key < table_key_end; table_key++) { /* Search a key with the same name. */ for (new_key= key_info_buffer; new_key < new_key_end; new_key++) @@ -7964,7 +7976,7 @@ bool mysql_compare_tables(TABLE *table, Alter_info *alter_info, for (new_key= key_info_buffer; new_key < new_key_end; new_key++) { /* Search a key with the same name. */ - for (table_key= table->key_info; table_key < table_key_end; table_key++) + for (table_key= table->s->key_info; table_key < table_key_end; table_key++) { if (!lex_string_cmp(system_charset_info, &table_key->name, &new_key->name))