Commit 86fc37b6 authored by Oleksandr Byelkin's avatar Oleksandr Byelkin

MDEV-19273: Server crash in MDL_ticket::has_stronger_or_equal_type or...

MDEV-19273: Server crash in MDL_ticket::has_stronger_or_equal_type or Assertion `thd->mdl_context.is_lock_owner(MDL_key::TABLE, table->db.str, table->table_name.str, MDL_SHARED)' failed in mysql_rm_table_no_locks

Early report error in case of DROP SEQUENCE <non-sequence>

Do not use error variable for other purposes except error.
parent bc2dc83c
...@@ -666,7 +666,7 @@ create temporary sequence s; ...@@ -666,7 +666,7 @@ create temporary sequence s;
drop temporary table s; drop temporary table s;
create temporary table s (i int); create temporary table s (i int);
drop temporary sequence s; drop temporary sequence s;
ERROR 42S02: Unknown SEQUENCE: 'test.s' ERROR 42S02: 'test.s' is not a SEQUENCE
drop table s; drop table s;
# #
# MDEV-15115 Assertion failure in CREATE SEQUENCE...ROW_FORMAT=REDUNDANT # MDEV-15115 Assertion failure in CREATE SEQUENCE...ROW_FORMAT=REDUNDANT
......
...@@ -489,7 +489,7 @@ drop table s; ...@@ -489,7 +489,7 @@ drop table s;
create temporary sequence s; create temporary sequence s;
drop temporary table s; drop temporary table s;
create temporary table s (i int); create temporary table s (i int);
--error ER_UNKNOWN_SEQUENCES --error ER_NOT_SEQUENCE2
drop temporary sequence s; drop temporary sequence s;
drop table s; drop table s;
......
...@@ -300,4 +300,63 @@ update t1 set p_first_name='Yunxi' where p_id=1; ...@@ -300,4 +300,63 @@ update t1 set p_first_name='Yunxi' where p_id=1;
drop view v2; drop view v2;
drop table t1,t2; drop table t1,t2;
drop sequence s1; drop sequence s1;
#
# MDEV-19273:Server crash in MDL_ticket::has_stronger_or_equal_type or
# Assertion `thd->mdl_context.is_lock_owner(MDL_key::TABLE,
# table->db.str, table->table_name.str, MDL_SHARED)' failed
# in mysql_rm_table_no_locks
#
CREATE TABLE t1 (a INT);
CREATE TEMPORARY TABLE tmp (b INT);
LOCK TABLE t1 READ;
DROP SEQUENCE tmp;
ERROR 42S02: 'test.tmp' is not a SEQUENCE
DROP TEMPORARY SEQUENCE tmp;
ERROR 42S02: 'test.tmp' is not a SEQUENCE
DROP SEQUENCE t1;
ERROR HY000: Table 't1' was locked with a READ lock and can't be updated
DROP TEMPORARY SEQUENCE t1;
ERROR 42S02: Unknown SEQUENCE: 'test.t1'
UNLOCK TABLES;
DROP SEQUENCE t1;
ERROR 42S02: 'test.t1' is not a SEQUENCE
DROP TEMPORARY SEQUENCE t1;
ERROR 42S02: Unknown SEQUENCE: 'test.t1'
DROP TABLE t1;
CREATE TABLE t (a INT);
CREATE TEMPORARY TABLE s (f INT);
CREATE SEQUENCE s;
LOCK TABLE t WRITE;
DROP SEQUENCE s;
ERROR 42S02: 'test.s' is not a SEQUENCE
DROP TEMPORARY SEQUENCE s;
ERROR 42S02: 'test.s' is not a SEQUENCE
UNLOCK TABLES;
CREATE TEMPORARY SEQUENCE s;
LOCK TABLE t WRITE;
DROP TEMPORARY SEQUENCE s;
UNLOCK TABLES;
DROP TEMPORARY TABLE s;
DROP SEQUENCE s;
create table s(a INT);
CREATE TEMPORARY TABLE s (f INT);
LOCK TABLE t WRITE;
DROP TEMPORARY TABLE s;
CREATE TEMPORARY TABLE s (f INT);
DROP TABLE s;
DROP TABLE s;
ERROR HY000: Table 's' was not locked with LOCK TABLES
UNLOCK TABLES;
DROP TABLE s;
CREATE VIEW v1 as SELECT * FROM t;
CREATE SEQUENCE s;
DROP SEQUENCE IF EXISTS v1;
Warnings:
Note 4091 Unknown SEQUENCE: 'test.v1'
DROP VIEW IF EXISTS s;
Warnings:
Note 4092 Unknown VIEW: 'test.s'
DROP VIEW v1;
DROP SEQUENCE s;
DROP TABLE t;
# End of 10.3 tests # End of 10.3 tests
...@@ -315,4 +315,68 @@ drop view v2; ...@@ -315,4 +315,68 @@ drop view v2;
drop table t1,t2; drop table t1,t2;
drop sequence s1; drop sequence s1;
--echo #
--echo # MDEV-19273:Server crash in MDL_ticket::has_stronger_or_equal_type or
--echo # Assertion `thd->mdl_context.is_lock_owner(MDL_key::TABLE,
--echo # table->db.str, table->table_name.str, MDL_SHARED)' failed
--echo # in mysql_rm_table_no_locks
--echo #
CREATE TABLE t1 (a INT);
CREATE TEMPORARY TABLE tmp (b INT);
LOCK TABLE t1 READ;
--error ER_NOT_SEQUENCE2
DROP SEQUENCE tmp;
--error ER_NOT_SEQUENCE2
DROP TEMPORARY SEQUENCE tmp;
--error ER_TABLE_NOT_LOCKED_FOR_WRITE
DROP SEQUENCE t1;
--error ER_UNKNOWN_SEQUENCES
DROP TEMPORARY SEQUENCE t1;
UNLOCK TABLES;
--error ER_NOT_SEQUENCE2
DROP SEQUENCE t1;
--error ER_UNKNOWN_SEQUENCES
DROP TEMPORARY SEQUENCE t1;
# Cleanup
DROP TABLE t1;
CREATE TABLE t (a INT);
CREATE TEMPORARY TABLE s (f INT);
CREATE SEQUENCE s;
LOCK TABLE t WRITE;
--error ER_NOT_SEQUENCE2
DROP SEQUENCE s;
--error ER_NOT_SEQUENCE2
DROP TEMPORARY SEQUENCE s;
UNLOCK TABLES;
CREATE TEMPORARY SEQUENCE s;
LOCK TABLE t WRITE;
DROP TEMPORARY SEQUENCE s;
UNLOCK TABLES;
DROP TEMPORARY TABLE s;
DROP SEQUENCE s;
create table s(a INT);
CREATE TEMPORARY TABLE s (f INT);
LOCK TABLE t WRITE;
DROP TEMPORARY TABLE s;
CREATE TEMPORARY TABLE s (f INT);
DROP TABLE s;
--error ER_TABLE_NOT_LOCKED
DROP TABLE s;
UNLOCK TABLES;
DROP TABLE s;
CREATE VIEW v1 as SELECT * FROM t;
CREATE SEQUENCE s;
DROP SEQUENCE IF EXISTS v1;
DROP VIEW IF EXISTS s;
DROP VIEW v1;
DROP SEQUENCE s;
DROP TABLE t;
--echo # End of 10.3 tests --echo # End of 10.3 tests
...@@ -2314,8 +2314,11 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, ...@@ -2314,8 +2314,11 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
{ {
bool is_trans= 0; bool is_trans= 0;
bool table_creation_was_logged= 0; bool table_creation_was_logged= 0;
bool real_table= FALSE;
LEX_CSTRING db= table->db; LEX_CSTRING db= table->db;
handlerton *table_type= 0; handlerton *table_type= 0;
// reset error state for this table
error= 0;
DBUG_PRINT("table", ("table_l: '%s'.'%s' table: %p s: %p", DBUG_PRINT("table", ("table_l: '%s'.'%s' table: %p s: %p",
table->db.str, table->table_name.str, table->table, table->db.str, table->table_name.str, table->table,
...@@ -2331,9 +2334,35 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, ...@@ -2331,9 +2334,35 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
thd->find_temporary_table(table) && thd->find_temporary_table(table) &&
table->mdl_request.ticket != NULL)); table->mdl_request.ticket != NULL));
if (table->open_type == OT_BASE_ONLY || !is_temporary_table(table) || if (table->open_type == OT_BASE_ONLY || !is_temporary_table(table))
(drop_sequence && table->table->s->table_type != TABLE_TYPE_SEQUENCE)) real_table= TRUE;
else if (drop_sequence &&
table->table->s->table_type != TABLE_TYPE_SEQUENCE)
{
was_table= (table->table->s->table_type == TABLE_TYPE_NORMAL);
was_view= (table->table->s->table_type == TABLE_TYPE_VIEW);
if (if_exists)
{
char buff[FN_REFLEN];
String tbl_name(buff, sizeof(buff), system_charset_info);
tbl_name.length(0);
tbl_name.append(&db);
tbl_name.append('.');
tbl_name.append(&table->table_name);
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_NOT_SEQUENCE2, ER_THD(thd, ER_NOT_SEQUENCE2),
tbl_name.c_ptr_safe());
/*
Our job is done here. This statement was added to avoid executing
unnecessary code farther below which in some strange corner cases
caused the server to crash (see MDEV-17896).
*/
goto log_query;
}
error= 1; error= 1;
goto non_critical_err;
}
else else
{ {
table_creation_was_logged= table->table->s->table_creation_was_logged; table_creation_was_logged= table->table->s->table_creation_was_logged;
...@@ -2342,29 +2371,28 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, ...@@ -2342,29 +2371,28 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
error= 1; error= 1;
goto err; goto err;
} }
error= 0;
table->table= 0; table->table= 0;
} }
if ((drop_temporary && if_exists) || !error) if ((drop_temporary && if_exists) || !real_table)
{ {
/* /*
This handles the case of temporary tables. We have the following cases: This handles the case of temporary tables. We have the following cases:
. "DROP TEMPORARY" was executed and a temporary table was affected . "DROP TEMPORARY" was executed and a temporary table was affected
(i.e. drop_temporary && !error) or the if_exists was specified (i.e. (i.e. drop_temporary && !real_table) or the
drop_temporary && if_exists). if_exists was specified (i.e. drop_temporary && if_exists).
. "DROP" was executed but a temporary table was affected (.i.e . "DROP" was executed but a temporary table was affected (.i.e
!error). !real_table).
*/ */
if (!dont_log_query && table_creation_was_logged) if (!dont_log_query && table_creation_was_logged)
{ {
/* /*
If there is an error, we don't know the type of the engine If there is an real_table, we don't know the type of the engine
at this point. So, we keep it in the trx-cache. at this point. So, we keep it in the trx-cache.
*/ */
is_trans= error ? TRUE : is_trans; is_trans= real_table ? TRUE : is_trans;
if (is_trans) if (is_trans)
trans_tmp_table_deleted= TRUE; trans_tmp_table_deleted= TRUE;
else else
...@@ -2391,7 +2419,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, ...@@ -2391,7 +2419,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
is no need to proceed with the code that tries to drop a regular is no need to proceed with the code that tries to drop a regular
table. table.
*/ */
if (!error) continue; if (!real_table) continue;
} }
else if (!drop_temporary) else if (!drop_temporary)
{ {
...@@ -2407,7 +2435,6 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, ...@@ -2407,7 +2435,6 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
reg_ext, 0); reg_ext, 0);
} }
DEBUG_SYNC(thd, "rm_table_no_locks_before_delete_table"); DEBUG_SYNC(thd, "rm_table_no_locks_before_delete_table");
error= 0;
if (drop_temporary || if (drop_temporary ||
(ha_table_exists(thd, &db, &alias, &table_type, &is_sequence) == 0 && (ha_table_exists(thd, &db, &alias, &table_type, &is_sequence) == 0 &&
table_type == 0) || table_type == 0) ||
...@@ -2447,6 +2474,11 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, ...@@ -2447,6 +2474,11 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
{ {
non_tmp_error = (drop_temporary ? non_tmp_error : TRUE); non_tmp_error = (drop_temporary ? non_tmp_error : TRUE);
error= 1; error= 1;
/*
non critical error (only for this table), so we continue.
Next we write it to wrong_tables and continue this loop
The same as "goto non_critical_err".
*/
} }
} }
else else
...@@ -2540,7 +2572,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, ...@@ -2540,7 +2572,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
} }
non_tmp_error|= MY_TEST(error); non_tmp_error|= MY_TEST(error);
} }
non_critical_err:
if (error) if (error)
{ {
if (wrong_tables.length()) if (wrong_tables.length())
......
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