Fix for bug#15447 Partitions: NULL is treated as zero
NULL value handling mysql-test/r/ndb_partition_error.result: Fix for bug#15447 Partitions: NULL is treated as zero test case mysql-test/r/partition.result: Fix for bug#15447 Partitions: NULL is treated as zero test case mysql-test/t/ndb_partition_error.test: Fix for bug#15447 Partitions: NULL is treated as zero test case mysql-test/t/partition.test: Fix for bug#15447 Partitions: NULL is treated as zero test case sql/partition_element.h: Fix for bug#15447 Partitions: NULL is treated as zero added null value flag to partition_element object sql/partition_info.h: Fix for bug#15447 Partitions: NULL is treated as zero added null value flag to partition_info object added has_null partition id variable
This commit is contained in:
parent
8cf8e4ed37
commit
807c7a6a49
@ -36,3 +36,12 @@ INSERT INTO t1 VALUES (2);
|
|||||||
UPDATE t1 SET id=5 WHERE id=2;
|
UPDATE t1 SET id=5 WHERE id=2;
|
||||||
ERROR HY000: Table has no partition for value 5
|
ERROR HY000: Table has no partition for value 5
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
create table t1 (a int,b int, c int)
|
||||||
|
engine = ndb
|
||||||
|
partition by list(a)
|
||||||
|
partitions 2
|
||||||
|
(partition x123 values in (11, 12),
|
||||||
|
partition x234 values in (5, 1));
|
||||||
|
insert into t1 values (NULL,1,1);
|
||||||
|
ERROR HY000: Table has no partition for value NULL
|
||||||
|
drop table t1;
|
||||||
|
@ -373,4 +373,53 @@ end//
|
|||||||
call p()//
|
call p()//
|
||||||
drop procedure p//
|
drop procedure p//
|
||||||
drop table t1//
|
drop table t1//
|
||||||
|
create table t1 (a int,b int,c int,key(a,b))
|
||||||
|
partition by range (a)
|
||||||
|
partitions 3
|
||||||
|
(partition x1 values less than (0) tablespace ts1,
|
||||||
|
partition x2 values less than (10) tablespace ts2,
|
||||||
|
partition x3 values less than maxvalue tablespace ts3);
|
||||||
|
insert into t1 values (NULL, 1, 1);
|
||||||
|
insert into t1 values (0, 1, 1);
|
||||||
|
insert into t1 values (12, 1, 1);
|
||||||
|
select partition_name, partition_description, table_rows
|
||||||
|
from information_schema.partitions where table_schema ='test';
|
||||||
|
partition_name partition_description table_rows
|
||||||
|
x1 0 1
|
||||||
|
x2 10 1
|
||||||
|
x3 MAXVALUE 1
|
||||||
|
drop table t1;
|
||||||
|
create table t1 (a int,b int, c int)
|
||||||
|
partition by list(a)
|
||||||
|
partitions 2
|
||||||
|
(partition x123 values in (11,12),
|
||||||
|
partition x234 values in (1 ,NULL, NULL));
|
||||||
|
ERROR HY000: Multiple definition of same constant in list partitioning
|
||||||
|
create table t1 (a int,b int, c int)
|
||||||
|
partition by list(a)
|
||||||
|
partitions 2
|
||||||
|
(partition x123 values in (11, NULL),
|
||||||
|
partition x234 values in (1 ,NULL));
|
||||||
|
ERROR HY000: Multiple definition of same constant in list partitioning
|
||||||
|
create table t1 (a int,b int, c int)
|
||||||
|
partition by list(a)
|
||||||
|
partitions 2
|
||||||
|
(partition x123 values in (11, 12),
|
||||||
|
partition x234 values in (5, 1));
|
||||||
|
insert into t1 values (NULL,1,1);
|
||||||
|
ERROR HY000: Table has no partition for value NULL
|
||||||
|
drop table t1;
|
||||||
|
create table t1 (a int,b int, c int)
|
||||||
|
partition by list(a)
|
||||||
|
partitions 2
|
||||||
|
(partition x123 values in (11, 12),
|
||||||
|
partition x234 values in (NULL, 1));
|
||||||
|
insert into t1 values (11,1,6);
|
||||||
|
insert into t1 values (NULL,1,1);
|
||||||
|
select partition_name, partition_description, table_rows
|
||||||
|
from information_schema.partitions where table_schema ='test';
|
||||||
|
partition_name partition_description table_rows
|
||||||
|
x123 11,12 1
|
||||||
|
x234 NULL,1 1
|
||||||
|
drop table t1;
|
||||||
End of 5.1 tests
|
End of 5.1 tests
|
||||||
|
@ -56,3 +56,16 @@ INSERT INTO t1 VALUES (2);
|
|||||||
--error ER_NO_PARTITION_FOR_GIVEN_VALUE
|
--error ER_NO_PARTITION_FOR_GIVEN_VALUE
|
||||||
UPDATE t1 SET id=5 WHERE id=2;
|
UPDATE t1 SET id=5 WHERE id=2;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# NULL for LIST partition
|
||||||
|
#
|
||||||
|
create table t1 (a int,b int, c int)
|
||||||
|
engine = ndb
|
||||||
|
partition by list(a)
|
||||||
|
partitions 2
|
||||||
|
(partition x123 values in (11, 12),
|
||||||
|
partition x234 values in (5, 1));
|
||||||
|
--error 1504
|
||||||
|
insert into t1 values (NULL,1,1);
|
||||||
|
drop table t1;
|
||||||
|
@ -483,4 +483,61 @@ drop procedure p//
|
|||||||
drop table t1//
|
drop table t1//
|
||||||
delimiter ;//
|
delimiter ;//
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #15447 Partitions: NULL is treated as zero
|
||||||
|
#
|
||||||
|
|
||||||
|
# NULL for RANGE partition
|
||||||
|
create table t1 (a int,b int,c int,key(a,b))
|
||||||
|
partition by range (a)
|
||||||
|
partitions 3
|
||||||
|
(partition x1 values less than (0) tablespace ts1,
|
||||||
|
partition x2 values less than (10) tablespace ts2,
|
||||||
|
partition x3 values less than maxvalue tablespace ts3);
|
||||||
|
|
||||||
|
insert into t1 values (NULL, 1, 1);
|
||||||
|
insert into t1 values (0, 1, 1);
|
||||||
|
insert into t1 values (12, 1, 1);
|
||||||
|
|
||||||
|
select partition_name, partition_description, table_rows
|
||||||
|
from information_schema.partitions where table_schema ='test';
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
# NULL for LIST partition
|
||||||
|
--error 1473
|
||||||
|
create table t1 (a int,b int, c int)
|
||||||
|
partition by list(a)
|
||||||
|
partitions 2
|
||||||
|
(partition x123 values in (11,12),
|
||||||
|
partition x234 values in (1 ,NULL, NULL));
|
||||||
|
|
||||||
|
--error 1473
|
||||||
|
create table t1 (a int,b int, c int)
|
||||||
|
partition by list(a)
|
||||||
|
partitions 2
|
||||||
|
(partition x123 values in (11, NULL),
|
||||||
|
partition x234 values in (1 ,NULL));
|
||||||
|
|
||||||
|
create table t1 (a int,b int, c int)
|
||||||
|
partition by list(a)
|
||||||
|
partitions 2
|
||||||
|
(partition x123 values in (11, 12),
|
||||||
|
partition x234 values in (5, 1));
|
||||||
|
--error 1504
|
||||||
|
insert into t1 values (NULL,1,1);
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
create table t1 (a int,b int, c int)
|
||||||
|
partition by list(a)
|
||||||
|
partitions 2
|
||||||
|
(partition x123 values in (11, 12),
|
||||||
|
partition x234 values in (NULL, 1));
|
||||||
|
|
||||||
|
insert into t1 values (11,1,6);
|
||||||
|
insert into t1 values (NULL,1,1);
|
||||||
|
|
||||||
|
select partition_name, partition_description, table_rows
|
||||||
|
from information_schema.partitions where table_schema ='test';
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
--echo End of 5.1 tests
|
--echo End of 5.1 tests
|
||||||
|
@ -6012,6 +6012,7 @@ void ha_ndbcluster::print_error(int error, myf errflag)
|
|||||||
{
|
{
|
||||||
char buf[100];
|
char buf[100];
|
||||||
my_error(ER_NO_PARTITION_FOR_GIVEN_VALUE, MYF(0),
|
my_error(ER_NO_PARTITION_FOR_GIVEN_VALUE, MYF(0),
|
||||||
|
m_part_info->part_expr->null_value ? "NULL" :
|
||||||
llstr(m_part_info->part_expr->val_int(), buf));
|
llstr(m_part_info->part_expr->val_int(), buf));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -5092,6 +5092,7 @@ void ha_partition::print_error(int error, myf errflag)
|
|||||||
{
|
{
|
||||||
char buf[100];
|
char buf[100];
|
||||||
my_error(ER_NO_PARTITION_FOR_GIVEN_VALUE, MYF(0),
|
my_error(ER_NO_PARTITION_FOR_GIVEN_VALUE, MYF(0),
|
||||||
|
m_part_info->part_expr->null_value ? "NULL" :
|
||||||
llstr(m_part_info->part_expr->val_int(), buf));
|
llstr(m_part_info->part_expr->val_int(), buf));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -51,13 +51,14 @@ public:
|
|||||||
handlerton *engine_type;
|
handlerton *engine_type;
|
||||||
enum partition_state part_state;
|
enum partition_state part_state;
|
||||||
uint16 nodegroup_id;
|
uint16 nodegroup_id;
|
||||||
|
bool has_null_value;
|
||||||
|
|
||||||
partition_element()
|
partition_element()
|
||||||
: part_max_rows(0), part_min_rows(0), partition_name(NULL),
|
: part_max_rows(0), part_min_rows(0), partition_name(NULL),
|
||||||
tablespace_name(NULL), range_value(0), part_comment(NULL),
|
tablespace_name(NULL), range_value(0), part_comment(NULL),
|
||||||
data_file_name(NULL), index_file_name(NULL),
|
data_file_name(NULL), index_file_name(NULL),
|
||||||
engine_type(NULL),part_state(PART_NORMAL),
|
engine_type(NULL),part_state(PART_NORMAL),
|
||||||
nodegroup_id(UNDEF_NODEGROUP)
|
nodegroup_id(UNDEF_NODEGROUP), has_null_value(FALSE)
|
||||||
{
|
{
|
||||||
subpartitions.empty();
|
subpartitions.empty();
|
||||||
list_val_list.empty();
|
list_val_list.empty();
|
||||||
|
@ -181,6 +181,9 @@ public:
|
|||||||
bool linear_hash_ind;
|
bool linear_hash_ind;
|
||||||
bool fixed;
|
bool fixed;
|
||||||
bool from_openfrm;
|
bool from_openfrm;
|
||||||
|
bool has_null_value;
|
||||||
|
uint has_null_part_id;
|
||||||
|
|
||||||
|
|
||||||
partition_info()
|
partition_info()
|
||||||
: get_partition_id(NULL), get_part_partition_id(NULL),
|
: get_partition_id(NULL), get_part_partition_id(NULL),
|
||||||
@ -211,7 +214,9 @@ public:
|
|||||||
list_of_part_fields(FALSE), list_of_subpart_fields(FALSE),
|
list_of_part_fields(FALSE), list_of_subpart_fields(FALSE),
|
||||||
linear_hash_ind(FALSE),
|
linear_hash_ind(FALSE),
|
||||||
fixed(FALSE),
|
fixed(FALSE),
|
||||||
from_openfrm(FALSE)
|
from_openfrm(FALSE),
|
||||||
|
has_null_value(FALSE),
|
||||||
|
has_null_part_id(0)
|
||||||
{
|
{
|
||||||
all_fields_in_PF.clear_all();
|
all_fields_in_PF.clear_all();
|
||||||
all_fields_in_PPF.clear_all();
|
all_fields_in_PPF.clear_all();
|
||||||
|
@ -531,6 +531,7 @@ static bool check_list_constants(partition_info *part_info)
|
|||||||
bool result= TRUE;
|
bool result= TRUE;
|
||||||
longlong curr_value, prev_value;
|
longlong curr_value, prev_value;
|
||||||
partition_element* part_def;
|
partition_element* part_def;
|
||||||
|
bool found_null= FALSE;
|
||||||
List_iterator<partition_element> list_func_it(part_info->partitions);
|
List_iterator<partition_element> list_func_it(part_info->partitions);
|
||||||
DBUG_ENTER("check_list_constants");
|
DBUG_ENTER("check_list_constants");
|
||||||
|
|
||||||
@ -556,6 +557,17 @@ static bool check_list_constants(partition_info *part_info)
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
part_def= list_func_it++;
|
part_def= list_func_it++;
|
||||||
|
if (part_def->has_null_value)
|
||||||
|
{
|
||||||
|
if (found_null)
|
||||||
|
{
|
||||||
|
my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
part_info->has_null_value= TRUE;
|
||||||
|
part_info->has_null_part_id= i;
|
||||||
|
found_null= TRUE;
|
||||||
|
}
|
||||||
List_iterator<longlong> list_val_it1(part_def->list_val_list);
|
List_iterator<longlong> list_val_it1(part_def->list_val_list);
|
||||||
while (list_val_it1++)
|
while (list_val_it1++)
|
||||||
no_list_values++;
|
no_list_values++;
|
||||||
@ -2041,6 +2053,16 @@ static int add_partition_values(File fptr, partition_info *part_info,
|
|||||||
err+= add_string(fptr, "VALUES IN ");
|
err+= add_string(fptr, "VALUES IN ");
|
||||||
uint no_items= p_elem->list_val_list.elements;
|
uint no_items= p_elem->list_val_list.elements;
|
||||||
err+= add_begin_parenthesis(fptr);
|
err+= add_begin_parenthesis(fptr);
|
||||||
|
if (p_elem->has_null_value)
|
||||||
|
{
|
||||||
|
err+= add_string(fptr, "NULL");
|
||||||
|
if (no_items == 0)
|
||||||
|
{
|
||||||
|
err+= add_end_parenthesis(fptr);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
err+= add_comma(fptr);
|
||||||
|
}
|
||||||
i= 0;
|
i= 0;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -2051,6 +2073,7 @@ static int add_partition_values(File fptr, partition_info *part_info,
|
|||||||
} while (++i < no_items);
|
} while (++i < no_items);
|
||||||
err+= add_end_parenthesis(fptr);
|
err+= add_end_parenthesis(fptr);
|
||||||
}
|
}
|
||||||
|
end:
|
||||||
return err + add_space(fptr);
|
return err + add_space(fptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2631,6 +2654,15 @@ int get_partition_id_list(partition_info *part_info,
|
|||||||
longlong part_func_value= part_val_int(part_info->part_expr);
|
longlong part_func_value= part_val_int(part_info->part_expr);
|
||||||
DBUG_ENTER("get_partition_id_list");
|
DBUG_ENTER("get_partition_id_list");
|
||||||
|
|
||||||
|
if (part_info->part_expr->null_value)
|
||||||
|
{
|
||||||
|
if (part_info->has_null_value)
|
||||||
|
{
|
||||||
|
*part_id= part_info->has_null_part_id;
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
goto notfound;
|
||||||
|
}
|
||||||
*func_value= part_func_value;
|
*func_value= part_func_value;
|
||||||
while (max_list_index >= min_list_index)
|
while (max_list_index >= min_list_index)
|
||||||
{
|
{
|
||||||
@ -2741,6 +2773,11 @@ int get_partition_id_range(partition_info *part_info,
|
|||||||
longlong part_func_value= part_val_int(part_info->part_expr);
|
longlong part_func_value= part_val_int(part_info->part_expr);
|
||||||
DBUG_ENTER("get_partition_id_int_range");
|
DBUG_ENTER("get_partition_id_int_range");
|
||||||
|
|
||||||
|
if (part_info->part_expr->null_value)
|
||||||
|
{
|
||||||
|
*part_id= 0;
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
while (max_part_id > min_part_id)
|
while (max_part_id > min_part_id)
|
||||||
{
|
{
|
||||||
loc_part_id= (max_part_id + min_part_id + 1) >> 1;
|
loc_part_id= (max_part_id + min_part_id + 1) >> 1;
|
||||||
@ -2814,6 +2851,10 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info,
|
|||||||
uint min_part_id= 0, max_part_id= max_partition, loc_part_id;
|
uint min_part_id= 0, max_part_id= max_partition, loc_part_id;
|
||||||
/* Get the partitioning function value for the endpoint */
|
/* Get the partitioning function value for the endpoint */
|
||||||
longlong part_func_value= part_val_int(part_info->part_expr);
|
longlong part_func_value= part_val_int(part_info->part_expr);
|
||||||
|
|
||||||
|
if (part_info->part_expr->null_value)
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
while (max_part_id > min_part_id)
|
while (max_part_id > min_part_id)
|
||||||
{
|
{
|
||||||
loc_part_id= (max_part_id + min_part_id + 1) >> 1;
|
loc_part_id= (max_part_id + min_part_id + 1) >> 1;
|
||||||
|
@ -3832,6 +3832,12 @@ static int get_schema_partitions_record(THD *thd, struct st_table_list *tables,
|
|||||||
uint no_items= part_elem->list_val_list.elements;
|
uint no_items= part_elem->list_val_list.elements;
|
||||||
tmp_str.length(0);
|
tmp_str.length(0);
|
||||||
tmp_res.length(0);
|
tmp_res.length(0);
|
||||||
|
if (part_elem->has_null_value)
|
||||||
|
{
|
||||||
|
tmp_str.append("NULL");
|
||||||
|
if (no_items > 0)
|
||||||
|
tmp_str.append(",");
|
||||||
|
}
|
||||||
while ((list_value= list_val_it++))
|
while ((list_value= list_val_it++))
|
||||||
{
|
{
|
||||||
tmp_res.set(*list_value, cs);
|
tmp_res.set(*list_value, cs);
|
||||||
|
@ -42,6 +42,12 @@
|
|||||||
#include <myisam.h>
|
#include <myisam.h>
|
||||||
#include <myisammrg.h>
|
#include <myisammrg.h>
|
||||||
|
|
||||||
|
typedef struct p_elem_val
|
||||||
|
{
|
||||||
|
longlong value;
|
||||||
|
bool null_value;
|
||||||
|
} part_elem_value;
|
||||||
|
|
||||||
int yylex(void *yylval, void *yythd);
|
int yylex(void *yylval, void *yythd);
|
||||||
|
|
||||||
const LEX_STRING null_lex_str={0,0};
|
const LEX_STRING null_lex_str={0,0};
|
||||||
@ -105,6 +111,7 @@ inline Item *is_truth_value(Item *A, bool v1, bool v2)
|
|||||||
sp_name *spname;
|
sp_name *spname;
|
||||||
struct st_lex *lex;
|
struct st_lex *lex;
|
||||||
sp_head *sphead;
|
sp_head *sphead;
|
||||||
|
struct p_elem_val *p_elem_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
%{
|
%{
|
||||||
@ -752,7 +759,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
|||||||
%type <ulonglong_number>
|
%type <ulonglong_number>
|
||||||
ulonglong_num size_number
|
ulonglong_num size_number
|
||||||
|
|
||||||
%type <longlong_number>
|
%type <p_elem_value>
|
||||||
part_bit_expr
|
part_bit_expr
|
||||||
|
|
||||||
%type <lock_type>
|
%type <lock_type>
|
||||||
@ -3781,7 +3788,7 @@ part_func_max:
|
|||||||
part_range_func:
|
part_range_func:
|
||||||
'(' part_bit_expr ')'
|
'(' part_bit_expr ')'
|
||||||
{
|
{
|
||||||
Lex->part_info->curr_part_elem->range_value= $2;
|
Lex->part_info->curr_part_elem->range_value= $2->value;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -3793,12 +3800,12 @@ part_list_func:
|
|||||||
part_list_item:
|
part_list_item:
|
||||||
part_bit_expr
|
part_bit_expr
|
||||||
{
|
{
|
||||||
longlong *value_ptr;
|
part_elem_value *value_ptr= $1;
|
||||||
if (!(value_ptr= (longlong*)sql_alloc(sizeof(longlong))) ||
|
if (!value_ptr->null_value &&
|
||||||
((*value_ptr= $1, FALSE) ||
|
Lex->part_info->curr_part_elem->
|
||||||
Lex->part_info->curr_part_elem->list_val_list.push_back(value_ptr)))
|
list_val_list.push_back((longlong*) &value_ptr->value))
|
||||||
{
|
{
|
||||||
mem_alloc_error(sizeof(longlong));
|
mem_alloc_error(sizeof(part_elem_value));
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3818,6 +3825,15 @@ part_bit_expr:
|
|||||||
|
|
||||||
context->table_list= 0;
|
context->table_list= 0;
|
||||||
thd->where= "partition function";
|
thd->where= "partition function";
|
||||||
|
|
||||||
|
part_elem_value *value_ptr=
|
||||||
|
(part_elem_value*)sql_alloc(sizeof(part_elem_value));
|
||||||
|
if (!value_ptr)
|
||||||
|
{
|
||||||
|
mem_alloc_error(sizeof(part_elem_value));
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
|
|
||||||
if (part_expr->fix_fields(YYTHD, (Item**)0) ||
|
if (part_expr->fix_fields(YYTHD, (Item**)0) ||
|
||||||
((context->table_list= save_list), FALSE) ||
|
((context->table_list= save_list), FALSE) ||
|
||||||
(!part_expr->const_item()) ||
|
(!part_expr->const_item()) ||
|
||||||
@ -3827,13 +3843,23 @@ part_bit_expr:
|
|||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
thd->where= save_where;
|
thd->where= save_where;
|
||||||
if (part_expr->result_type() != INT_RESULT)
|
value_ptr->value= part_expr->val_int();
|
||||||
|
if ((value_ptr->null_value= part_expr->null_value))
|
||||||
|
{
|
||||||
|
if (Lex->part_info->curr_part_elem->has_null_value)
|
||||||
|
{
|
||||||
|
my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0));
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
|
Lex->part_info->curr_part_elem->has_null_value= TRUE;
|
||||||
|
}
|
||||||
|
else if (part_expr->result_type() != INT_RESULT &&
|
||||||
|
!part_expr->null_value)
|
||||||
{
|
{
|
||||||
yyerror(ER(ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR));
|
yyerror(ER(ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR));
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
item_value= part_expr->val_int();
|
$$= value_ptr;
|
||||||
$$= item_value;
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user