Commit db9b2bdc authored by unknown's avatar unknown

Post push fix

Fixed a missed case in the patch for Bug#31931.
Also makes Bug#33722 a duplicate of Bug#31931.
Added tests for better coverage.
Replaced some legacy function calls.


mysql-test/r/partition.result:
  Added tests for better coverage
mysql-test/r/partition_datatype.result:
  Added tests for better coverage
mysql-test/r/partition_error.result:
  Added tests for better coverage
mysql-test/suite/parts/inc/partition_engine.inc:
  Bug#31931: Mix of handlers error message
  
  Bug#33722 is fixed within this patch too
mysql-test/suite/parts/r/partition_engine_innodb.result:
  Bug#31931: Mix of handlers error message
  
  Bug#33722 is fixed within this patch too
mysql-test/suite/parts/r/partition_engine_myisam.result:
  Bug#31931: Mix of handlers error message
  
  Bug#33722 is fixed within this patch too
mysql-test/t/partition.test:
  Added tests for better coverage
mysql-test/t/partition_datatype.test:
  Added tests for better coverage
mysql-test/t/partition_error.test:
  Added tests for Bug#31931
sql/partition_info.cc:
  Bug#31931: Mix of handlers error message
  
  Fixed case where given info->db_type not matched
  thd->lex->create_info.db_type
  
  And the check for inconsistent subpartition engines-clauses.
sql/sql_partition.cc:
  Changed ha_legacy_type to ha_resolve_storage_engine_name
sql/sql_table.cc:
  Changed ha_legacy_type to ha_resolve_storage_engine_name
parent c37fdbcd
......@@ -1052,6 +1052,12 @@ test.t1 repair note The storage engine for the table doesn't support repair
OPTIMIZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 optimize note The storage engine for the table doesn't support optimize
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check note The storage engine for the table doesn't support check
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 analyze note The storage engine for the table doesn't support analyze
drop table t1;
drop procedure if exists mysqltest_1;
create table t1 (a int)
......@@ -1290,6 +1296,14 @@ ALTER TABLE t1 OPTIMIZE PARTITION p1 EXTENDED;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'EXTENDED' at line 1
ALTER TABLE t1 ANALYZE PARTITION p1 EXTENDED;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'EXTENDED' at line 1
ALTER TABLE t1 ANALYZE PARTITION p1;
ERROR 42000: The storage engine for the table doesn't support analyze partition
ALTER TABLE t1 CHECK PARTITION p1;
ERROR 42000: The storage engine for the table doesn't support check partition
ALTER TABLE t1 REPAIR PARTITION p1;
ERROR 42000: The storage engine for the table doesn't support repair partition
ALTER TABLE t1 OPTIMIZE PARTITION p1;
ERROR 42000: The storage engine for the table doesn't support optimize partition
DROP TABLE t1;
CREATE TABLE t1 (s1 BIGINT UNSIGNED)
PARTITION BY RANGE (s1) (
......
......@@ -135,9 +135,17 @@ drop table t1;
# test with null allowed
create table t1 (a bit) partition by key (a);
insert into t1 values (b'1');
insert into t1 values (NULL);
select hex(a) from t1 where a = b'1';
hex(a)
1
select hex(a) from t1 where a is NULL;
hex(a)
NULL
select hex(a) from t1 order by a;
hex(a)
NULL
1
drop table t1;
create table t1 (a tinyint) partition by key (a);
insert into t1 values (2);
......
drop table if exists t1;
CREATE TABLE t1 (a INT)
PARTITION BY HASH (a)
( PARTITION p0 ENGINE=MyISAM,
PARTITION p1);
ERROR HY000: The mix of handlers in the partitions is not allowed in this version of MySQL
CREATE TABLE t1 (a INT)
PARTITION BY LIST (a)
SUBPARTITION BY HASH (a)
( PARTITION p0 VALUES IN (0)
( SUBPARTITION s0, SUBPARTITION s1 ENGINE=MyISAM, SUBPARTITION s2),
PARTITION p1 VALUES IN (1)
( SUBPARTITION s3 ENGINE=MyISAM, SUBPARTITION s4, SUBPARTITION s5 ENGINE=MyISAM));
ERROR HY000: The mix of handlers in the partitions is not allowed in this version of MySQL
CREATE TABLE t1 (
a int
)
......
......@@ -112,11 +112,23 @@ SUBPARTITION BY HASH(f_int1)
(SUBPARTITION subpart21 STORAGE ENGINE = $engine,
SUBPARTITION subpart22 STORAGE ENGINE = $engine)
);
--echo # this should fail with ER_MIX_HANDLER_ERROR
--echo # after fixing Bug#33722
--error ER_MIX_HANDLER_ERROR
eval CREATE TABLE t1 (
$column_list
)
PARTITION BY RANGE(f_int1)
SUBPARTITION BY HASH(f_int1)
( PARTITION part1 VALUES LESS THAN ($max_row_div2)
(SUBPARTITION subpart11 STORAGE ENGINE = $engine,
SUBPARTITION subpart12 STORAGE ENGINE = $engine),
PARTITION part2 VALUES LESS THAN $MAX_VALUE
(SUBPARTITION subpart21,
SUBPARTITION subpart22 )
);
eval CREATE TABLE t1 (
$column_list
)
ENGINE = $engine
PARTITION BY RANGE(f_int1)
SUBPARTITION BY HASH(f_int1)
( PARTITION part1 VALUES LESS THAN ($max_row_div2)
......@@ -135,14 +147,38 @@ DROP TABLE t1;
--echo # 4 Storage engine assignment after partition name + after name of
--echo # subpartitions belonging to another partition
--echo #------------------------------------------------------------------------
--echo # this should work
--echo # after fixing Bug#33722
--error ER_MIX_HANDLER_ERROR
eval CREATE TABLE t1 (
$column_list
)
PARTITION BY RANGE(f_int1)
SUBPARTITION BY HASH(f_int1)
( PARTITION part1 VALUES LESS THAN ($max_row_div2)
(SUBPARTITION subpart11,
SUBPARTITION subpart12),
PARTITION part2 VALUES LESS THAN $MAX_VALUE
(SUBPARTITION subpart21 STORAGE ENGINE = $engine,
SUBPARTITION subpart22 STORAGE ENGINE = $engine)
);
eval CREATE TABLE t1 (
$column_list
)
ENGINE = $engine
PARTITION BY RANGE(f_int1)
SUBPARTITION BY HASH(f_int1)
( PARTITION part1 VALUES LESS THAN ($max_row_div2) ENGINE = $engine
(SUBPARTITION subpart11,
SUBPARTITION subpart12),
PARTITION part2 VALUES LESS THAN $MAX_VALUE
(SUBPARTITION subpart21,
SUBPARTITION subpart22 STORAGE ENGINE = $engine)
);
DROP TABLE t1;
eval CREATE TABLE t1 (
$column_list
)
PARTITION BY RANGE(f_int1)
SUBPARTITION BY HASH(f_int1)
( PARTITION part1 VALUES LESS THAN ($max_row_div2) ENGINE = $engine
(SUBPARTITION subpart11,
SUBPARTITION subpart12),
......@@ -150,13 +186,10 @@ SUBPARTITION BY HASH(f_int1)
(SUBPARTITION subpart21 STORAGE ENGINE = $engine,
SUBPARTITION subpart22 STORAGE ENGINE = $engine)
);
#INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
#SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template;
#--source suite/parts/inc/partition_check.inc
#DROP TABLE t1;
--echo # this should work
--echo # after fixing Bug#33722
--error ER_MIX_HANDLER_ERROR
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template;
--source suite/parts/inc/partition_check.inc
DROP TABLE t1;
eval CREATE TABLE t1 (
$column_list
)
......@@ -166,13 +199,13 @@ SUBPARTITION BY HASH(f_int1)
(SUBPARTITION subpart11 STORAGE ENGINE = $engine,
SUBPARTITION subpart12 STORAGE ENGINE = $engine),
PARTITION part2 VALUES LESS THAN $MAX_VALUE ENGINE = $engine
(SUBPARTITION subpart21,
(SUBPARTITION subpart21 ENGINE = $engine,
SUBPARTITION subpart22)
);
#INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
#SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template;
#--source suite/parts/inc/partition_check.inc
#DROP TABLE t1;
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template;
--source suite/parts/inc/partition_check.inc
DROP TABLE t1;
#
--echo #------------------------------------------------------------------------
--echo # 5 Precedence of storage engine assignments (if there is any)
......@@ -208,10 +241,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template;
DROP TABLE t1;
--echo # 6.2 Storage engine assignment after partition name + after
--echo # subpartition name
# in partition part + in sub partition part
--echo # this should work
--echo # after fixing Bug#33722
--error ER_MIX_HANDLER_ERROR
--echo # in partition part + in sub partition part
eval CREATE TABLE t1 (
$column_list
)
......@@ -224,10 +254,10 @@ SUBPARTITION BY HASH(f_int1)
(SUBPARTITION subpart21 STORAGE ENGINE = $engine,
SUBPARTITION subpart22 STORAGE ENGINE = $engine)
);
#INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
#SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template;
#--source suite/parts/inc/partition_check.inc
#DROP TABLE t1;
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template;
--source suite/parts/inc/partition_check.inc
DROP TABLE t1;
--echo #------------------------------------------------------------------------
--echo # 6 Session default engine differs from engine used within create table
......
......@@ -1215,13 +1215,15 @@ DROP TABLE t1;
#
# Bug 17455 Partitions: Wrong message and error when using Repair/Optimize
# table on partitioned table
#
# (added check/analyze for gcov of Bug#20129)
create table t1 (a int)
engine=MEMORY
partition by key (a);
REPAIR TABLE t1;
OPTIMIZE TABLE t1;
CHECK TABLE t1;
ANALYZE TABLE t1;
drop table t1;
......@@ -1524,7 +1526,7 @@ select c1 from t1 group by (select c0 from t1 limit 1);
drop table t1;
# Bug #30495: optimize table t1,t2,t3 extended errors
#
# (added more maintenace commands for Bug#20129
CREATE TABLE t1(a int)
PARTITION BY RANGE (a) (
PARTITION p1 VALUES LESS THAN (10),
......@@ -1534,6 +1536,14 @@ PARTITION BY RANGE (a) (
ALTER TABLE t1 OPTIMIZE PARTITION p1 EXTENDED;
--error ER_PARSE_ERROR
ALTER TABLE t1 ANALYZE PARTITION p1 EXTENDED;
--error ER_CHECK_NOT_IMPLEMENTED
ALTER TABLE t1 ANALYZE PARTITION p1;
--error ER_CHECK_NOT_IMPLEMENTED
ALTER TABLE t1 CHECK PARTITION p1;
--error ER_CHECK_NOT_IMPLEMENTED
ALTER TABLE t1 REPAIR PARTITION p1;
--error ER_CHECK_NOT_IMPLEMENTED
ALTER TABLE t1 OPTIMIZE PARTITION p1;
DROP TABLE t1;
#
......
......@@ -103,7 +103,10 @@ drop table t1;
-- echo # test with null allowed
create table t1 (a bit) partition by key (a);
insert into t1 values (b'1');
insert into t1 values (NULL);
select hex(a) from t1 where a = b'1';
select hex(a) from t1 where a is NULL;
select hex(a) from t1 order by a;
drop table t1;
create table t1 (a tinyint) partition by key (a);
insert into t1 values (2);
......
......@@ -8,6 +8,24 @@
drop table if exists t1;
--enable_warnings
#
# Bug#31931: Mix of handlers error message
#
--error ER_MIX_HANDLER_ERROR
CREATE TABLE t1 (a INT)
PARTITION BY HASH (a)
( PARTITION p0 ENGINE=MyISAM,
PARTITION p1);
--error ER_MIX_HANDLER_ERROR
CREATE TABLE t1 (a INT)
PARTITION BY LIST (a)
SUBPARTITION BY HASH (a)
( PARTITION p0 VALUES IN (0)
( SUBPARTITION s0, SUBPARTITION s1 ENGINE=MyISAM, SUBPARTITION s2),
PARTITION p1 VALUES IN (1)
( SUBPARTITION s3 ENGINE=MyISAM, SUBPARTITION s4, SUBPARTITION s5 ENGINE=MyISAM));
#
# Bug 29368:
# Incorrect error, 1467, for syntax error when creating partition
......
......@@ -464,15 +464,15 @@ static bool check_engine_condition(partition_element *p_elem,
{
DBUG_ENTER("check_engine_condition");
DBUG_PRINT("enter", ("p_eng %u t_eng %u t_eng_set %u first %u state %u",
ha_legacy_type(p_elem->engine_type),
ha_legacy_type(*engine_type),
DBUG_PRINT("enter", ("p_eng %s t_eng %s t_eng_set %u first %u state %u",
ha_resolve_storage_engine_name(p_elem->engine_type),
ha_resolve_storage_engine_name(*engine_type),
table_engine_set, *first, p_elem->part_state));
if (*first && !table_engine_set)
{
*engine_type= p_elem->engine_type;
DBUG_PRINT("info", ("setting table_engine = %u",
ha_legacy_type(*engine_type)));
DBUG_PRINT("info", ("setting table_engine = %s",
ha_resolve_storage_engine_name(*engine_type)));
}
*first= FALSE;
if ((table_engine_set &&
......@@ -522,8 +522,8 @@ bool partition_info::check_engine_mix(handlerton *engine_type,
bool first= TRUE;
uint no_parts= partitions.elements;
DBUG_ENTER("partition_info::check_engine_mix");
DBUG_PRINT("info", ("in: engine_type = %u, table_engine_set = %u",
ha_legacy_type(engine_type),
DBUG_PRINT("info", ("in: engine_type = %s, table_engine_set = %u",
ha_resolve_storage_engine_name(engine_type),
table_engine_set));
if (no_parts)
{
......@@ -532,8 +532,8 @@ bool partition_info::check_engine_mix(handlerton *engine_type,
do
{
partition_element *part_elem= part_it++;
DBUG_PRINT("info", ("part = %d engine = %d table_engine_set %u",
i, ha_legacy_type(part_elem->engine_type),
DBUG_PRINT("info", ("part = %d engine = %s table_engine_set %u",
i, ha_resolve_storage_engine_name(part_elem->engine_type),
table_engine_set));
if (is_sub_partitioned() &&
part_elem->subpartitions.elements)
......@@ -544,8 +544,8 @@ bool partition_info::check_engine_mix(handlerton *engine_type,
do
{
partition_element *sub_elem= sub_it++;
DBUG_PRINT("info", ("sub = %d engine = %u table_engie_set %u",
j, ha_legacy_type(sub_elem->engine_type),
DBUG_PRINT("info", ("sub = %d engine = %s table_engie_set %u",
j, ha_resolve_storage_engine_name(sub_elem->engine_type),
table_engine_set));
if (check_engine_condition(sub_elem, table_engine_set,
&engine_type, &first))
......@@ -561,8 +561,8 @@ bool partition_info::check_engine_mix(handlerton *engine_type,
goto error;
} while (++i < no_parts);
}
DBUG_PRINT("info", ("engine_type = %u",
ha_legacy_type(engine_type)));
DBUG_PRINT("info", ("engine_type = %s",
ha_resolve_storage_engine_name(engine_type)));
if (!engine_type)
engine_type= old_engine_type;
if (engine_type->flags & HTON_NO_PARTITION)
......@@ -570,8 +570,8 @@ bool partition_info::check_engine_mix(handlerton *engine_type,
my_error(ER_PARTITION_MERGE_ERROR, MYF(0));
DBUG_RETURN(TRUE);
}
DBUG_PRINT("info", ("out: engine_type = %u",
ha_legacy_type(engine_type)));
DBUG_PRINT("info", ("out: engine_type = %s",
ha_resolve_storage_engine_name(engine_type)));
DBUG_ASSERT(engine_type != partition_hton);
DBUG_RETURN(FALSE);
error:
......@@ -859,6 +859,8 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
DBUG_ENTER("partition_info::check_partition_info");
DBUG_ASSERT(default_engine_type != partition_hton);
DBUG_PRINT("info", ("default table_engine = %s",
ha_resolve_storage_engine_name(table_engine)));
if (check_partition_function)
{
int err= 0;
......@@ -913,10 +915,16 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
the table and all partitions/subpartitions are set.
So when ALTER it is already set on table level
*/
if (thd->lex->create_info.used_fields & HA_CREATE_USED_ENGINE)
if (info && info->used_fields & HA_CREATE_USED_ENGINE)
{
table_engine_set= TRUE;
table_engine= thd->lex->create_info.db_type;
table_engine= info->db_type;
/* if partition_hton, use thd->lex->create_info */
if (table_engine == partition_hton)
table_engine= thd->lex->create_info.db_type;
DBUG_ASSERT(table_engine != partition_hton);
DBUG_PRINT("info", ("Using table_engine = %s",
ha_resolve_storage_engine_name(table_engine)));
}
else
{
......@@ -924,6 +932,8 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
if (thd->lex->sql_command != SQLCOM_CREATE_TABLE)
{
table_engine_set= TRUE;
DBUG_PRINT("info", ("No create, table_engine = %s",
ha_resolve_storage_engine_name(table_engine)));
DBUG_ASSERT(table_engine && table_engine != partition_hton);
}
}
......@@ -941,11 +951,6 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
do
{
partition_element *part_elem= part_it++;
if (part_elem->engine_type == NULL)
{
no_parts_not_set++;
part_elem->engine_type= default_engine_type;
}
#ifdef HAVE_READLINK
if (!my_use_symdir || (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE))
#endif
......@@ -960,23 +965,29 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
}
if (!is_sub_partitioned())
{
if (part_elem->engine_type == NULL)
{
no_parts_not_set++;
part_elem->engine_type= default_engine_type;
}
if (check_table_name(part_elem->partition_name,
strlen(part_elem->partition_name)))
{
my_error(ER_WRONG_PARTITION_NAME, MYF(0));
goto end;
}
DBUG_PRINT("info", ("part = %d engine = %d",
i, ha_legacy_type(part_elem->engine_type)));
DBUG_PRINT("info", ("part = %d engine = %s",
i, ha_resolve_storage_engine_name(part_elem->engine_type)));
}
else
{
uint j= 0;
uint no_subparts_not_set= 0;
List_iterator<partition_element> sub_it(part_elem->subpartitions);
partition_element *sub_elem;
do
{
partition_element *sub_elem= sub_it++;
sub_elem= sub_it++;
if (check_table_name(sub_elem->partition_name,
strlen(sub_elem->partition_name)))
{
......@@ -985,24 +996,41 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
}
if (sub_elem->engine_type == NULL)
{
sub_elem->engine_type= default_engine_type;
no_subparts_not_set++;
if (part_elem->engine_type != NULL)
sub_elem->engine_type= part_elem->engine_type;
else
{
sub_elem->engine_type= default_engine_type;
no_subparts_not_set++;
}
}
DBUG_PRINT("info", ("part = %d sub = %d engine = %u",
i, j, ha_legacy_type(sub_elem->engine_type)));
DBUG_PRINT("info", ("part = %d sub = %d engine = %s", i, j,
ha_resolve_storage_engine_name(sub_elem->engine_type)));
} while (++j < no_subparts);
if (prev_no_subparts_not_set == (no_subparts + 1))
if (prev_no_subparts_not_set == (no_subparts + 1) &&
(no_subparts_not_set == 0 || no_subparts_not_set == no_subparts))
prev_no_subparts_not_set= no_subparts_not_set;
if (!table_engine_set &&
prev_no_subparts_not_set == no_subparts_not_set &&
no_subparts_not_set != 0 &&
no_subparts_not_set != no_subparts)
prev_no_subparts_not_set != no_subparts_not_set)
{
DBUG_PRINT("info", ("no_subparts_not_set = %u no_subparts = %u",
no_subparts_not_set, no_subparts));
my_error(ER_MIX_HANDLER_ERROR, MYF(0));
goto end;
}
if (part_elem->engine_type == NULL)
{
if (no_subparts_not_set == 0)
part_elem->engine_type= sub_elem->engine_type;
else
{
no_parts_not_set++;
part_elem->engine_type= default_engine_type;
}
}
}
} while (++i < no_parts);
if (!table_engine_set &&
......@@ -1021,9 +1049,8 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
goto end;
}
if (table_engine == partition_hton)
DBUG_PRINT("info", ("Table engine set to partition_hton"));
DBUG_ASSERT(default_engine_type == table_engine);
DBUG_ASSERT(table_engine != partition_hton &&
default_engine_type == table_engine);
if (eng_type)
*eng_type= table_engine;
......
......@@ -3819,9 +3819,9 @@ bool mysql_unpack_partition(THD *thd,
DBUG_PRINT("info", ("Successful parse"));
part_info= lex.part_info;
DBUG_PRINT("info", ("default engine = %d, default_db_type = %d",
ha_legacy_type(part_info->default_engine_type),
ha_legacy_type(default_db_type)));
DBUG_PRINT("info", ("default engine = %s, default_db_type = %s",
ha_resolve_storage_engine_name(part_info->default_engine_type),
ha_resolve_storage_engine_name(default_db_type)));
if (is_create_table_ind && old_lex->sql_command == SQLCOM_CREATE_TABLE)
{
if (old_lex->create_info.options & HA_LEX_CREATE_TABLE_LIKE)
......@@ -4041,8 +4041,8 @@ static bool check_native_partitioned(HA_CREATE_INFO *create_info,bool *ret_val,
DBUG_ASSERT(engine_type && engine_type != partition_hton);
}
}
DBUG_PRINT("info", ("engine_type = %u, table_engine_set = %u",
ha_legacy_type(engine_type),
DBUG_PRINT("info", ("engine_type = %s, table_engine_set = %u",
ha_resolve_storage_engine_name(engine_type),
table_engine_set));
if (part_info->check_engine_mix(engine_type, table_engine_set))
goto error;
......
......@@ -3295,8 +3295,9 @@ bool mysql_create_table_no_lock(THD *thd,
}
}
}
DBUG_PRINT("info", ("db_type = %d",
ha_legacy_type(part_info->default_engine_type)));
DBUG_PRINT("info", ("db_type = %s create_info->db_type = %s",
ha_resolve_storage_engine_name(part_info->default_engine_type),
ha_resolve_storage_engine_name(create_info->db_type)));
if (part_info->check_partition_info(thd, &engine_type, file,
create_info, TRUE))
goto err;
......@@ -3321,7 +3322,7 @@ bool mysql_create_table_no_lock(THD *thd,
Assign the partition handler as the handler of the table.
*/
DBUG_PRINT("info", ("db_type: %d",
ha_legacy_type(create_info->db_type)));
ha_resolve_storage_engine_name(create_info->db_type)));
delete file;
create_info->db_type= partition_hton;
if (!(file= get_ha_partition(part_info)))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment