MDEV-22164 without validation for exchange partition/convert in

1. WITHOUT/WITH VALIDATION may be added to EXCHANGE PARTITION or CONVERT TABLE:

  alter table tp exchange partition p1 with table t with validation;
  alter table tp exchange partition p1 with table t; -- same as with validation
  alter table tp exchange partition p1 with table t without validation;

2. Optional THAN keyword for RANGE partitioning. Normally you type:

  create table tp (a int primary key) partition by range (a) (
    partition p0 values less than (100),
    partition p1 values less than maxvalue);

  Now you may type (PARTITION keyword is also optional):

  create table tp (a int primary key) partition by range (a) (
    p0 values less (100),
    p1 values less maxvalue);
This commit is contained in:
Aleksey Midenkov 2023-12-06 18:44:38 +03:00
parent 485773adce
commit 5462b61b0c
7 changed files with 332 additions and 5 deletions

View File

@ -358,3 +358,177 @@ disconnect con1;
connection default;
drop user u@localhost;
drop database db;
#
# MDEV-22164 without validation for exchange partition/convert in
#
create table validation(x int);
drop table validation;
create table t (a int primary key);
create table tp (a int primary key) partition by range (a) (
partition p0 values less than (100),
# Cunning syntax (same as above)
p1 values less (300));
insert into t values (1), (99);
insert into tp values (2), (200);
select * from t order by a;
a
1
99
select * from tp partition (p0) order by a;
a
2
select * from tp partition (p1) order by a;
a
200
alter table tp exchange partition p0 with table t;
select * from t order by a;
a
2
select * from tp partition (p0) order by a;
a
1
99
select * from tp partition (p1) order by a;
a
200
alter table tp exchange partition p0 with table t;
select * from t order by a;
a
1
99
select * from tp partition (p0) order by a;
a
2
select * from tp partition (p1) order by a;
a
200
alter table tp exchange partition p1 with table t;
ERROR HY000: Found a row that does not match the partition
alter table tp exchange partition p1 with table t with validation;
ERROR HY000: Found a row that does not match the partition
alter table tp exchange partition p1 with table t without validation;
select * from t order by a;
a
200
select * from tp partition (p1) order by a;
a
1
99
alter table tp check partition p0;
Table Op Msg_type Msg_text
test.tp check status OK
alter table tp check partition p1;
Table Op Msg_type Msg_text
test.tp check error Found a misplaced row
test.tp check error Partition p1 returned error
test.tp check error Upgrade required. Please do "REPAIR TABLE `tp`" or dump/reload to fix it!
alter table tp exchange partition p1 with table t with validation;
alter table tp exchange partition p1 with table t with validation;
ERROR HY000: Found a row that does not match the partition
select * from t order by a;
a
1
99
select * from tp partition (p1) order by a;
a
200
create or replace procedure validation()
alter table tp exchange partition p1 with table t with validation;
create or replace procedure without_validation()
alter table tp exchange partition p1 with table t without validation;
call validation;
ERROR HY000: Found a row that does not match the partition
call without_validation;
call validation;
call validation;
ERROR HY000: Found a row that does not match the partition
call without_validation;
select * from t order by a;
a
200
select * from tp partition (p1) order by a;
a
1
99
call validation;
select * from t order by a;
a
1
99
select * from tp partition (p1) order by a;
a
200
drop procedure validation;
drop procedure without_validation;
prepare validation from "alter table tp exchange partition p1 with table t with validation";
prepare without_validation from "alter table tp exchange partition p1 with table t without validation";
execute validation;
ERROR HY000: Found a row that does not match the partition
execute without_validation;
execute validation;
execute validation;
ERROR HY000: Found a row that does not match the partition
execute without_validation;
select * from t order by a;
a
200
select * from tp partition (p1) order by a;
a
1
99
execute validation;
select * from t order by a;
a
1
99
select * from tp partition (p1) order by a;
a
200
drop prepare validation;
drop prepare without_validation;
alter table tp convert table t to partition p2 values less (maxvalue);
ERROR HY000: Found a row that does not match the partition
alter table tp convert table t to partition p2 values less (maxvalue) with validation;
ERROR HY000: Found a row that does not match the partition
alter table tp convert table t to partition p2 values less (maxvalue) without validation;
select * from tp partition (p0) order by a;
a
2
select * from tp partition (p1) order by a;
a
200
select * from tp partition (p2) order by a;
a
1
99
create table t (a int primary key);
insert t values (1), (2);
create or replace table tp (a int primary key)
partition by hash(a) partitions 2;
insert tp values (1), (2), (3), (4);
alter table tp exchange partition p0 with table t;
ERROR HY000: Found a row that does not match the partition
alter table tp exchange partition p0 with table t without validation;
select * from t;
a
2
4
alter table tp exchange partition p0 with table t;
drop table tp;
create or replace table tp (a int primary key)
partition by list(a) (
partition p0 values in (2, 3, 4),
partition p1 values in (12, 13, 14),
partition p2 values in (52, 53, 54));
insert tp values (12), (2), (3), (4);
alter table tp exchange partition p0 with table t;
ERROR HY000: Table has no partition for value 0
alter table tp exchange partition p0 with table t without validation;
select * from t;
a
2
3
4
alter table tp exchange partition p0 with table t;
drop tables tp, t;
# End of 11.4 tests

View File

@ -319,3 +319,132 @@ alter table t1 convert table tp to partition p2 values less than (1000);
--connection default
drop user u@localhost;
drop database db;
--echo #
--echo # MDEV-22164 without validation for exchange partition/convert in
--echo #
create table validation(x int);
drop table validation;
create table t (a int primary key);
create table tp (a int primary key) partition by range (a) (
partition p0 values less than (100),
# Cunning syntax (same as above)
p1 values less (300));
insert into t values (1), (99);
insert into tp values (2), (200);
select * from t order by a;
select * from tp partition (p0) order by a;
select * from tp partition (p1) order by a;
alter table tp exchange partition p0 with table t;
select * from t order by a;
select * from tp partition (p0) order by a;
select * from tp partition (p1) order by a;
alter table tp exchange partition p0 with table t;
select * from t order by a;
select * from tp partition (p0) order by a;
select * from tp partition (p1) order by a;
--error ER_ROW_DOES_NOT_MATCH_PARTITION
alter table tp exchange partition p1 with table t;
--error ER_ROW_DOES_NOT_MATCH_PARTITION
alter table tp exchange partition p1 with table t with validation;
alter table tp exchange partition p1 with table t without validation;
select * from t order by a;
select * from tp partition (p1) order by a;
alter table tp check partition p0;
alter table tp check partition p1;
alter table tp exchange partition p1 with table t with validation;
--error ER_ROW_DOES_NOT_MATCH_PARTITION
alter table tp exchange partition p1 with table t with validation;
select * from t order by a;
select * from tp partition (p1) order by a;
# SP
create or replace procedure validation()
alter table tp exchange partition p1 with table t with validation;
create or replace procedure without_validation()
alter table tp exchange partition p1 with table t without validation;
--error ER_ROW_DOES_NOT_MATCH_PARTITION
call validation;
call without_validation;
call validation;
--error ER_ROW_DOES_NOT_MATCH_PARTITION
call validation;
call without_validation;
select * from t order by a;
select * from tp partition (p1) order by a;
call validation;
select * from t order by a;
select * from tp partition (p1) order by a;
drop procedure validation;
drop procedure without_validation;
# PS
prepare validation from "alter table tp exchange partition p1 with table t with validation";
prepare without_validation from "alter table tp exchange partition p1 with table t without validation";
--error ER_ROW_DOES_NOT_MATCH_PARTITION
execute validation;
execute without_validation;
execute validation;
--error ER_ROW_DOES_NOT_MATCH_PARTITION
execute validation;
execute without_validation;
select * from t order by a;
select * from tp partition (p1) order by a;
execute validation;
select * from t order by a;
select * from tp partition (p1) order by a;
drop prepare validation;
drop prepare without_validation;
# CONVERT IN
--error ER_ROW_DOES_NOT_MATCH_PARTITION
alter table tp convert table t to partition p2 values less (maxvalue);
--error ER_ROW_DOES_NOT_MATCH_PARTITION
alter table tp convert table t to partition p2 values less (maxvalue) with validation;
alter table tp convert table t to partition p2 values less (maxvalue) without validation;
select * from tp partition (p0) order by a;
select * from tp partition (p1) order by a;
select * from tp partition (p2) order by a;
# Hash
create table t (a int primary key);
insert t values (1), (2);
create or replace table tp (a int primary key)
partition by hash(a) partitions 2;
insert tp values (1), (2), (3), (4);
--error ER_ROW_DOES_NOT_MATCH_PARTITION
alter table tp exchange partition p0 with table t;
alter table tp exchange partition p0 with table t without validation;
select * from t;
alter table tp exchange partition p0 with table t;
drop table tp;
# List
create or replace table tp (a int primary key)
partition by list(a) (
partition p0 values in (2, 3, 4),
partition p1 values in (12, 13, 14),
partition p2 values in (52, 53, 54));
insert tp values (12), (2), (3), (4);
--error ER_NO_PARTITION_FOR_GIVEN_VALUE
alter table tp exchange partition p0 with table t;
alter table tp exchange partition p0 with table t without validation;
select * from t;
alter table tp exchange partition p0 with table t;
drop tables tp, t;
--echo # End of 11.4 tests

View File

@ -714,6 +714,7 @@ SYMBOL symbols[] = {
{ "UTC_DATE", SYM(UTC_DATE_SYM)},
{ "UTC_TIME", SYM(UTC_TIME_SYM)},
{ "UTC_TIMESTAMP", SYM(UTC_TIMESTAMP_SYM)},
{ "VALIDATION", SYM(VALIDATION_SYM)},
{ "VALUE", SYM(VALUE_SYM)},
{ "VALUES", SYM(VALUES)},
{ "VARBINARY", SYM(VARBINARY)},

View File

@ -1301,6 +1301,7 @@ void LEX::start(THD *thd_arg)
default_used= 0;
with_rownum= FALSE;
is_lex_started= 1;
without_validation= 0;
create_info.lex_start();
name= null_clex_str;
@ -3932,7 +3933,7 @@ LEX::LEX()
: explain(NULL), result(0), part_info(NULL), arena_for_set_stmt(0),
mem_root_for_set_stmt(0), json_table(NULL), analyze_stmt(0),
default_used(0),
with_rownum(0), is_lex_started(0), option_type(OPT_DEFAULT),
with_rownum(0), is_lex_started(0), without_validation(0), option_type(OPT_DEFAULT),
context_analysis_only(0), sphead(0), sp_mem_root_ptr(nullptr),
limit_rows_examined_cnt(ULONGLONG_MAX)
{

View File

@ -3440,6 +3440,7 @@ public:
bool default_used:1; /* using default() function */
bool with_rownum:1; /* Using rownum() function */
bool is_lex_started:1; /* If lex_start() did run. For debugging. */
bool without_validation:1; /* exchange or convert partition WITHOUT VALIDATION */
/*
This variable is used in post-parse stage to declare that sum-functions,

View File

@ -4107,6 +4107,9 @@ bool verify_data_with_partition(TABLE *table, TABLE *part_table,
DBUG_ASSERT(table && table->file && part_table && part_table->part_info &&
part_table->file);
if (table->in_use->lex->without_validation)
DBUG_RETURN(false);
/*
Verify all table rows.
First implementation uses full scan + evaluates partition functions for

View File

@ -1151,6 +1151,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%token <kwd> UPGRADE_SYM
%token <kwd> USER_SYM /* SQL-2003-R */
%token <kwd> USE_FRM
%token <kwd> VALIDATION_SYM /* MYSQL */
%token <kwd> VALUE_SYM /* SQL-2003-R */
%token <kwd> VARCHAR2_MARIADB_SYM
%token <kwd> VARCHAR2_ORACLE_SYM /* Oracle-R, PLSQL-R */
@ -4932,6 +4933,10 @@ part_name:
}
;
opt_than:
/* empty */
| THAN_SYM;
opt_part_values:
/* empty */
{
@ -4949,7 +4954,7 @@ opt_part_values:
else
part_info->part_type= HASH_PARTITION;
}
| VALUES_LESS_SYM THAN_SYM
| VALUES_LESS_SYM opt_than
{
LEX *lex= Lex;
partition_info *part_info= lex->part_info;
@ -7497,13 +7502,13 @@ alter_commands:
}
| reorg_partition_rule
| EXCHANGE_SYM PARTITION_SYM alt_part_name_item
WITH TABLE_SYM table_ident have_partitioning
WITH TABLE_SYM table_ident opt_without_validation have_partitioning
{
if (Lex->stmt_alter_table_exchange_partition($6))
MYSQL_YYABORT;
}
| CONVERT_SYM PARTITION_SYM alt_part_name_item
TO_SYM TABLE_SYM table_ident have_partitioning
TO_SYM TABLE_SYM table_ident opt_without_validation have_partitioning
{
LEX *lex= Lex;
if (Lex->stmt_alter_table($6))
@ -7543,7 +7548,7 @@ alter_commands:
lex->alter_info.partition_flags|= ALTER_PARTITION_ADD |
ALTER_PARTITION_CONVERT_IN;
}
TO_SYM PARTITION_SYM part_definition
TO_SYM PARTITION_SYM part_definition opt_without_validation have_partitioning
{
LEX *lex= Lex;
lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_table();
@ -7870,6 +7875,18 @@ alter_list_item:
}
;
opt_without_validation:
/* empty */
| WITH VALIDATION_SYM
{
Lex->without_validation= 0;
}
| WITHOUT VALIDATION_SYM
{
Lex->without_validation= 1;
}
;
opt_index_lock_algorithm:
/* empty */
| alter_lock_option
@ -16303,6 +16320,7 @@ keyword_sp_var_and_label:
| VIEW_SYM
| VIRTUAL_SYM
| VISIBLE_SYM
| VALIDATION_SYM
| VALUE_SYM
| WARNINGS
| WAIT_SYM