diff --git a/mysql-test/r/func_json.result b/mysql-test/r/func_json.result index 6a77648efa5..eff8f5c9c92 100644 --- a/mysql-test/r/func_json.result +++ b/mysql-test/r/func_json.result @@ -618,3 +618,14 @@ connection default; set @@global.max_allowed_packet = default; set @@global.net_buffer_length = default; disconnect newconn; +create table t1(j longtext, p longtext); +insert into t1 values +('{"a":1,"b":2,"c":3}','$.a'), +('{"a":1,"b":2,"c":3}','$.b'), +('{"a":1,"b":2,"c":3}','$.c'); +select j, p, json_remove(j, p) from t1; +j p json_remove(j, p) +{"a":1,"b":2,"c":3} $.a {"b": 2, "c": 3} +{"a":1,"b":2,"c":3} $.b {"a": 1, "c": 3} +{"a":1,"b":2,"c":3} $.c {"a": 1, "b": 2} +drop table t1; diff --git a/mysql-test/suite/innodb/r/trigger_error.result b/mysql-test/suite/innodb/r/trigger_error.result new file mode 100644 index 00000000000..ef5f910e1a2 --- /dev/null +++ b/mysql-test/suite/innodb/r/trigger_error.result @@ -0,0 +1,28 @@ +CREATE TABLE t1 (i INT) ENGINE=InnoDB; +CREATE TABLE t2 (i INT) ENGINE=InnoDB; +CREATE OR REPLACE TRIGGER tr1 +AFTER UPDATE ON t2 +FOR EACH ROW +INSERT INTO tlog (i) VALUES (1); +INSERT IGNORE INTO t2 VALUES (1); +CREATE TRIGGER IF NOT EXISTS tr2 +BEFORE INSERT ON t2 +FOR EACH ROW +INSERT INTO tlog (i) VALUES (2); +START TRANSACTION; +INSERT INTO t1 VALUES (1); +UPDATE t2 SET i = 3; +ERROR 42S02: Table 'test.tlog' doesn't exist +INSERT INTO t1 VALUES (2); +INSERT INTO t2 VALUES (4); +ERROR 42S02: Table 'test.tlog' doesn't exist +UPDATE t1 SET i = 4 LIMIT 1; +COMMIT; +SELECT * FROM t1; +i +4 +2 +SELECT * FROM t2; +i +1 +DROP TABLE t1,t2; diff --git a/mysql-test/suite/innodb/t/trigger_error.test b/mysql-test/suite/innodb/t/trigger_error.test new file mode 100644 index 00000000000..0334f2b353c --- /dev/null +++ b/mysql-test/suite/innodb/t/trigger_error.test @@ -0,0 +1,31 @@ +--source include/have_innodb.inc + +CREATE TABLE t1 (i INT) ENGINE=InnoDB; +CREATE TABLE t2 (i INT) ENGINE=InnoDB; + +CREATE OR REPLACE TRIGGER tr1 + AFTER UPDATE ON t2 + FOR EACH ROW + INSERT INTO tlog (i) VALUES (1); + +INSERT IGNORE INTO t2 VALUES (1); + +CREATE TRIGGER IF NOT EXISTS tr2 + BEFORE INSERT ON t2 + FOR EACH ROW + INSERT INTO tlog (i) VALUES (2); + +START TRANSACTION; +INSERT INTO t1 VALUES (1); +--error ER_NO_SUCH_TABLE +UPDATE t2 SET i = 3; +INSERT INTO t1 VALUES (2); +--error ER_NO_SUCH_TABLE +INSERT INTO t2 VALUES (4); +UPDATE t1 SET i = 4 LIMIT 1; +COMMIT; + +SELECT * FROM t1; +SELECT * FROM t2; + +DROP TABLE t1,t2; diff --git a/mysql-test/t/func_json.test b/mysql-test/t/func_json.test index 74692c475f4..72b8681ac44 100644 --- a/mysql-test/t/func_json.test +++ b/mysql-test/t/func_json.test @@ -263,3 +263,14 @@ set @@global.max_allowed_packet = default; set @@global.net_buffer_length = default; --disconnect newconn + +# +# MDEV-12262 Assertion `!null_value' failed in virtual bool Item::send on JSON_REMOVE. +# +create table t1(j longtext, p longtext); +insert into t1 values + ('{"a":1,"b":2,"c":3}','$.a'), + ('{"a":1,"b":2,"c":3}','$.b'), + ('{"a":1,"b":2,"c":3}','$.c'); +select j, p, json_remove(j, p) from t1; +drop table t1; diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index f3090a4097f..b8471dc8244 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -2633,6 +2633,7 @@ v_found: str->length(0); if (append_simple(str, js->ptr(), rem_start - js->ptr()) || + (je.state == JST_KEY && n_item > 0 && str->append(",", 1)) || append_simple(str, rem_end, js->end() - rem_end)) goto js_error; /* Out of memory. */ @@ -2658,6 +2659,7 @@ v_found: if (json_nice(&je, str, Item_func_json_format::LOOSE)) goto js_error; + null_value= 0; return str; js_error: diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index e984a6d14d8..8f63af78b43 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -7448,6 +7448,8 @@ ER_GEOJSON_NOT_CLOSED eng "Incorrect GeoJSON format - polygon not closed." ER_JSON_PATH_EMPTY eng "Path expression '$' is not allowed in argument %d to function '%s'." +ER_SLAVE_SAME_ID + eng "A slave with the same server_uuid/server_id as this slave has connected to the master" ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION eng "Illegal parameter data types %s and %s for operation '%s'" ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION diff --git a/sql/signal_handler.cc b/sql/signal_handler.cc index dc90fcae576..efcc9a3f0b2 100644 --- a/sql/signal_handler.cc +++ b/sql/signal_handler.cc @@ -201,6 +201,9 @@ extern "C" sig_handler handle_fatal_signal(int sig) case ABORT_QUERY_HARD: kreason= "ABORT_QUERY"; break; + case KILL_SLAVE_SAME_ID: + kreason= "KILL_SLAVE_SAME_ID"; + break; } my_safe_printf_stderr("%s", "\n" "Trying to get some variables.\n" diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 19846da8e8c..fef16acbd20 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1987,6 +1987,8 @@ int killed_errno(killed_state killed) case KILL_SERVER: case KILL_SERVER_HARD: DBUG_RETURN(ER_SERVER_SHUTDOWN); + case KILL_SLAVE_SAME_ID: + DBUG_RETURN(ER_SLAVE_SAME_ID); } DBUG_RETURN(0); // Keep compiler happy } diff --git a/sql/sql_class.h b/sql/sql_class.h index d5afa0a89dd..5b18f99022f 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -477,17 +477,23 @@ enum killed_state ABORT_QUERY_HARD= 7, KILL_TIMEOUT= 8, KILL_TIMEOUT_HARD= 9, + /* + When binlog reading thread connects to the server it kills + all the binlog threads with the same ID. + */ + KILL_SLAVE_SAME_ID= 10, /* All of the following killed states will kill the connection KILL_CONNECTION must be the first of these and it must start with an even number (becasue of HARD bit)! */ - KILL_CONNECTION= 10, - KILL_CONNECTION_HARD= 11, - KILL_SYSTEM_THREAD= 12, - KILL_SYSTEM_THREAD_HARD= 13, - KILL_SERVER= 14, - KILL_SERVER_HARD= 15 + KILL_CONNECTION= 12, + KILL_CONNECTION_HARD= 13, + KILL_SYSTEM_THREAD= 14, + KILL_SYSTEM_THREAD_HARD= 15, + KILL_SERVER= 16, + KILL_SERVER_HARD= 17, + }; extern int killed_errno(killed_state killed); diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 2a22810b8c2..0180671977c 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -2910,6 +2910,13 @@ err: THD_STAGE_INFO(thd, stage_waiting_to_finalize_termination); RUN_HOOK(binlog_transmit, transmit_stop, (thd, flags)); + if (info->thd->killed == KILL_SLAVE_SAME_ID) + { + info->errmsg= "A slave with the same server_uuid/server_id as this slave " + "has connected to the master"; + info->error= ER_SLAVE_SAME_ID; + } + const bool binlog_open = my_b_inited(&log); if (file >= 0) { @@ -2921,7 +2928,8 @@ err: thd->variables.max_allowed_packet= old_max_allowed_packet; delete info->fdev; - if (info->error == ER_MASTER_FATAL_ERROR_READING_BINLOG && binlog_open) + if ((info->error == ER_MASTER_FATAL_ERROR_READING_BINLOG || + info->error == ER_SLAVE_SAME_ID) && binlog_open) { /* detailing the fatal error message with coordinates @@ -3392,7 +3400,7 @@ void kill_zombie_dump_threads(uint32 slave_server_id) it will be slow because it will iterate through the list again. We just to do kill the thread ourselves. */ - tmp->awake(KILL_QUERY); + tmp->awake(KILL_SLAVE_SAME_ID); mysql_mutex_unlock(&tmp->LOCK_thd_data); } } diff --git a/storage/innobase/include/ut0dbg.h b/storage/innobase/include/ut0dbg.h index 5a373c57c0c..706579a3b9f 100644 --- a/storage/innobase/include/ut0dbg.h +++ b/storage/innobase/include/ut0dbg.h @@ -61,7 +61,7 @@ ut_dbg_assertion_failed( ut_dbg_assertion_failed(0, __FILE__, __LINE__) /** Debug assertion */ -#define ut_ad(EXPR) DBUG_ASSERT(EXPR) +#define ut_ad DBUG_ASSERT #ifdef UNIV_DEBUG /** Debug statement. Does nothing unless UNIV_DEBUG is defined. */ #define ut_d(EXPR) EXPR diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index 7c757a027d4..481e14d44de 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -2005,10 +2005,9 @@ trx_undo_report_row_operation( undo->empty = FALSE; undo->top_page_no = page_no; undo->top_offset = offset; - undo->top_undo_no = trx->undo_no; + undo->top_undo_no = trx->undo_no++; undo->guess_block = undo_block; - trx->undo_no++; trx->undo_rseg_space = rseg->space; mutex_exit(&trx->undo_mutex); diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index cc41d318188..1a997330a9e 100644 --- a/storage/innobase/trx/trx0roll.cc +++ b/storage/innobase/trx/trx0roll.cc @@ -990,11 +990,11 @@ trx_roll_pop_top_rec_of_trx(trx_t* trx, roll_ptr_t* roll_ptr, mem_heap_t* heap) trx_undo_t* temp = trx->rsegs.m_noredo.undo; const undo_no_t limit = trx->roll_limit; - ut_ad(!insert || !update || !insert->top_undo_no + ut_ad(!insert || !update || insert->empty || update->empty || insert->top_undo_no != update->top_undo_no); - ut_ad(!insert || !temp || !insert->top_undo_no + ut_ad(!insert || !temp || insert->empty || temp->empty || insert->top_undo_no != temp->top_undo_no); - ut_ad(!update || !temp || !update->top_undo_no + ut_ad(!update || !temp || update->empty || temp->empty || update->top_undo_no != temp->top_undo_no); if (insert && !insert->empty && limit <= insert->top_undo_no) {