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:
parent
485773adce
commit
5462b61b0c
@ -358,3 +358,177 @@ disconnect con1;
|
|||||||
connection default;
|
connection default;
|
||||||
drop user u@localhost;
|
drop user u@localhost;
|
||||||
drop database db;
|
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
|
||||||
|
@ -319,3 +319,132 @@ alter table t1 convert table tp to partition p2 values less than (1000);
|
|||||||
--connection default
|
--connection default
|
||||||
drop user u@localhost;
|
drop user u@localhost;
|
||||||
drop database db;
|
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
|
||||||
|
@ -714,6 +714,7 @@ SYMBOL symbols[] = {
|
|||||||
{ "UTC_DATE", SYM(UTC_DATE_SYM)},
|
{ "UTC_DATE", SYM(UTC_DATE_SYM)},
|
||||||
{ "UTC_TIME", SYM(UTC_TIME_SYM)},
|
{ "UTC_TIME", SYM(UTC_TIME_SYM)},
|
||||||
{ "UTC_TIMESTAMP", SYM(UTC_TIMESTAMP_SYM)},
|
{ "UTC_TIMESTAMP", SYM(UTC_TIMESTAMP_SYM)},
|
||||||
|
{ "VALIDATION", SYM(VALIDATION_SYM)},
|
||||||
{ "VALUE", SYM(VALUE_SYM)},
|
{ "VALUE", SYM(VALUE_SYM)},
|
||||||
{ "VALUES", SYM(VALUES)},
|
{ "VALUES", SYM(VALUES)},
|
||||||
{ "VARBINARY", SYM(VARBINARY)},
|
{ "VARBINARY", SYM(VARBINARY)},
|
||||||
|
@ -1301,6 +1301,7 @@ void LEX::start(THD *thd_arg)
|
|||||||
default_used= 0;
|
default_used= 0;
|
||||||
with_rownum= FALSE;
|
with_rownum= FALSE;
|
||||||
is_lex_started= 1;
|
is_lex_started= 1;
|
||||||
|
without_validation= 0;
|
||||||
|
|
||||||
create_info.lex_start();
|
create_info.lex_start();
|
||||||
name= null_clex_str;
|
name= null_clex_str;
|
||||||
@ -3932,7 +3933,7 @@ LEX::LEX()
|
|||||||
: explain(NULL), result(0), part_info(NULL), arena_for_set_stmt(0),
|
: explain(NULL), result(0), part_info(NULL), arena_for_set_stmt(0),
|
||||||
mem_root_for_set_stmt(0), json_table(NULL), analyze_stmt(0),
|
mem_root_for_set_stmt(0), json_table(NULL), analyze_stmt(0),
|
||||||
default_used(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),
|
context_analysis_only(0), sphead(0), sp_mem_root_ptr(nullptr),
|
||||||
limit_rows_examined_cnt(ULONGLONG_MAX)
|
limit_rows_examined_cnt(ULONGLONG_MAX)
|
||||||
{
|
{
|
||||||
|
@ -3440,6 +3440,7 @@ public:
|
|||||||
bool default_used:1; /* using default() function */
|
bool default_used:1; /* using default() function */
|
||||||
bool with_rownum:1; /* Using rownum() function */
|
bool with_rownum:1; /* Using rownum() function */
|
||||||
bool is_lex_started:1; /* If lex_start() did run. For debugging. */
|
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,
|
This variable is used in post-parse stage to declare that sum-functions,
|
||||||
|
@ -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 &&
|
DBUG_ASSERT(table && table->file && part_table && part_table->part_info &&
|
||||||
part_table->file);
|
part_table->file);
|
||||||
|
|
||||||
|
if (table->in_use->lex->without_validation)
|
||||||
|
DBUG_RETURN(false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Verify all table rows.
|
Verify all table rows.
|
||||||
First implementation uses full scan + evaluates partition functions for
|
First implementation uses full scan + evaluates partition functions for
|
||||||
|
@ -1151,6 +1151,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
|
|||||||
%token <kwd> UPGRADE_SYM
|
%token <kwd> UPGRADE_SYM
|
||||||
%token <kwd> USER_SYM /* SQL-2003-R */
|
%token <kwd> USER_SYM /* SQL-2003-R */
|
||||||
%token <kwd> USE_FRM
|
%token <kwd> USE_FRM
|
||||||
|
%token <kwd> VALIDATION_SYM /* MYSQL */
|
||||||
%token <kwd> VALUE_SYM /* SQL-2003-R */
|
%token <kwd> VALUE_SYM /* SQL-2003-R */
|
||||||
%token <kwd> VARCHAR2_MARIADB_SYM
|
%token <kwd> VARCHAR2_MARIADB_SYM
|
||||||
%token <kwd> VARCHAR2_ORACLE_SYM /* Oracle-R, PLSQL-R */
|
%token <kwd> VARCHAR2_ORACLE_SYM /* Oracle-R, PLSQL-R */
|
||||||
@ -4932,6 +4933,10 @@ part_name:
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
opt_than:
|
||||||
|
/* empty */
|
||||||
|
| THAN_SYM;
|
||||||
|
|
||||||
opt_part_values:
|
opt_part_values:
|
||||||
/* empty */
|
/* empty */
|
||||||
{
|
{
|
||||||
@ -4949,7 +4954,7 @@ opt_part_values:
|
|||||||
else
|
else
|
||||||
part_info->part_type= HASH_PARTITION;
|
part_info->part_type= HASH_PARTITION;
|
||||||
}
|
}
|
||||||
| VALUES_LESS_SYM THAN_SYM
|
| VALUES_LESS_SYM opt_than
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
partition_info *part_info= lex->part_info;
|
partition_info *part_info= lex->part_info;
|
||||||
@ -7497,13 +7502,13 @@ alter_commands:
|
|||||||
}
|
}
|
||||||
| reorg_partition_rule
|
| reorg_partition_rule
|
||||||
| EXCHANGE_SYM PARTITION_SYM alt_part_name_item
|
| 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))
|
if (Lex->stmt_alter_table_exchange_partition($6))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
| CONVERT_SYM PARTITION_SYM alt_part_name_item
|
| 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;
|
LEX *lex= Lex;
|
||||||
if (Lex->stmt_alter_table($6))
|
if (Lex->stmt_alter_table($6))
|
||||||
@ -7543,7 +7548,7 @@ alter_commands:
|
|||||||
lex->alter_info.partition_flags|= ALTER_PARTITION_ADD |
|
lex->alter_info.partition_flags|= ALTER_PARTITION_ADD |
|
||||||
ALTER_PARTITION_CONVERT_IN;
|
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 *lex= Lex;
|
||||||
lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_table();
|
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:
|
opt_index_lock_algorithm:
|
||||||
/* empty */
|
/* empty */
|
||||||
| alter_lock_option
|
| alter_lock_option
|
||||||
@ -16303,6 +16320,7 @@ keyword_sp_var_and_label:
|
|||||||
| VIEW_SYM
|
| VIEW_SYM
|
||||||
| VIRTUAL_SYM
|
| VIRTUAL_SYM
|
||||||
| VISIBLE_SYM
|
| VISIBLE_SYM
|
||||||
|
| VALIDATION_SYM
|
||||||
| VALUE_SYM
|
| VALUE_SYM
|
||||||
| WARNINGS
|
| WARNINGS
|
||||||
| WAIT_SYM
|
| WAIT_SYM
|
||||||
|
Loading…
x
Reference in New Issue
Block a user