From a441a569157bf75303e3f9f485211c4b5d4f6129 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Wed, 20 Oct 2021 19:53:49 +0300 Subject: Fix comment --- sql/sql_explain.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc index ec58145bada..16d5daee5c7 100644 --- a/sql/sql_explain.cc +++ b/sql/sql_explain.cc @@ -1735,7 +1735,7 @@ void Explain_table_access::print_explain_json(Explain_query *query, /* - Elements in this array match members of enum Extra_tag, defined in + Elements in this array match members of enum explain_extra_tag, defined in sql_explain.h */ -- cgit v1.2.1 From 481aa0af46930f2252cb8160358b5bd0fd4a8be6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 25 Oct 2021 15:14:43 +0300 Subject: MDEV-23267 Assertion on --bootstrap --innodb-force-recovery SysTablespace::file_not_found(): If the system tablespace cannot be found and innodb_force_recovery has been specified, refuse to start up. The system tablespace is necessary for accessing any InnoDB tables, because it contains the TRX_SYS page (the state of transactions) and the InnoDB data dictionary. This is similar to our handling of innodb_read_only except that we will happily create the InnoDB temporary tablespace even if innodb_force_recovry is set. --- storage/innobase/fsp/fsp0sysspace.cc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/storage/innobase/fsp/fsp0sysspace.cc b/storage/innobase/fsp/fsp0sysspace.cc index dc5a27e2f2c..1e2db8cc12f 100644 --- a/storage/innobase/fsp/fsp0sysspace.cc +++ b/storage/innobase/fsp/fsp0sysspace.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2013, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2021, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -684,13 +685,18 @@ SysTablespace::file_not_found( { file.m_exists = false; - if (srv_read_only_mode && !m_ignore_read_only) { + if (m_ignore_read_only) { + } else if (srv_read_only_mode) { ib::error() << "Can't create file '" << file.filepath() << "' when --innodb-read-only is set"; - return(DB_ERROR); + } else if (srv_force_recovery && space_id() == TRX_SYS_SPACE) { + ib::error() << "Can't create file '" << file.filepath() + << "' when --innodb-force-recovery is set"; + return DB_ERROR; + } - } else if (&file == &m_files.front()) { + if (&file == &m_files.front()) { /* First data file. */ ut_a(!*create_new_db); -- cgit v1.2.1 From d22c8cae00f7a7517c9b8228efbb543037c23c97 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 25 Oct 2021 10:48:24 +0200 Subject: compilation fixes for sys-devel/gcc-11.2.0:11 --- sql/item_timefunc.cc | 1 - storage/innobase/include/univ.i | 6 ++++++ storage/innobase/include/ut0byte.ic | 6 +++--- storage/innobase/pars/pars0grm.cc | 4 ++++ storage/innobase/pars/pars0grm.y | 4 ++++ storage/maria/ma_loghandler.c | 5 ++--- 6 files changed, 19 insertions(+), 7 deletions(-) diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index a40c2e18b91..fd5ab057b8b 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2832,7 +2832,6 @@ bool Item_func_timediff::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) DBUG_ASSERT(fixed == 1); int l_sign= 1; MYSQL_TIME l_time1,l_time2,l_time3; - ErrConvTime str(&l_time3); /* the following may be true in, for example, date_add(timediff(...), ... */ if (fuzzy_date & TIME_NO_ZERO_IN_DATE) diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index a97b6758441..d302770b230 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -240,6 +240,12 @@ easy way to get it to work. See http://bugs.mysql.com/bug.php?id=52263. */ # define UNIV_INTERN #endif +#if defined(__GNUC__) && (__GNUC__ >= 11) +# define ATTRIBUTE_ACCESS(X) __attribute__((access X)) +#else +# define ATTRIBUTE_ACCESS(X) +#endif + #ifndef MY_ATTRIBUTE #if defined(__GNUC__) # define MY_ATTRIBUTE(A) __attribute__(A) diff --git a/storage/innobase/include/ut0byte.ic b/storage/innobase/include/ut0byte.ic index b5b3d73fea8..8ca54c06dbc 100644 --- a/storage/innobase/include/ut0byte.ic +++ b/storage/innobase/include/ut0byte.ic @@ -77,7 +77,7 @@ ut_uint64_align_up( /*********************************************************//** The following function rounds up a pointer to the nearest aligned address. @return aligned pointer */ -UNIV_INLINE +UNIV_INLINE ATTRIBUTE_ACCESS((none,1)) void* ut_align( /*=====*/ @@ -97,7 +97,7 @@ ut_align( The following function rounds down a pointer to the nearest aligned address. @return aligned pointer */ -UNIV_INLINE +UNIV_INLINE ATTRIBUTE_ACCESS((none,1)) void* ut_align_down( /*==========*/ @@ -117,7 +117,7 @@ ut_align_down( The following function computes the offset of a pointer from the nearest aligned address. @return distance from aligned pointer */ -UNIV_INLINE +UNIV_INLINE ATTRIBUTE_ACCESS((none,1)) ulint ut_align_offset( /*============*/ diff --git a/storage/innobase/pars/pars0grm.cc b/storage/innobase/pars/pars0grm.cc index 7e10a783310..10d0d0becd7 100644 --- a/storage/innobase/pars/pars0grm.cc +++ b/storage/innobase/pars/pars0grm.cc @@ -79,6 +79,10 @@ que_node_t */ #include "que0que.h" #include "row0sel.h" +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wfree-nonheap-object" +#endif + #define YYSTYPE que_node_t* /* #define __STDC__ */ diff --git a/storage/innobase/pars/pars0grm.y b/storage/innobase/pars/pars0grm.y index 625ed41bbd4..3fb0865f608 100644 --- a/storage/innobase/pars/pars0grm.y +++ b/storage/innobase/pars/pars0grm.y @@ -38,6 +38,10 @@ que_node_t */ #include "que0que.h" #include "row0sel.h" +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wfree-nonheap-object" +#endif + #define YYSTYPE que_node_t* /* #define __STDC__ */ diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index b98fbe29e1f..8773e80942f 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -3395,10 +3395,9 @@ static uint16 translog_get_chunk_header_length(uchar *chunk) DBUG_PRINT("info", ("TRANSLOG_CHUNK_LNGTH = 3")); DBUG_RETURN(3); break; - default: - DBUG_ASSERT(0); - DBUG_RETURN(0); /* Keep compiler happy */ } + DBUG_ASSERT(0); + DBUG_RETURN(0); /* Keep compiler happy */ } -- cgit v1.2.1 From d627d00b13ab2f2c0954ea7b77202470cb102944 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Thu, 21 Oct 2021 15:11:20 +0400 Subject: MDEV-26556 An improper locking bug(s) due to unreleased lock. Get rid of the global big_buffer. --- mysql-test/suite/plugins/r/server_audit.result | 4 ++++ mysql-test/suite/plugins/t/server_audit.test | 2 ++ plugin/server_audit/server_audit.c | 30 ++++++-------------------- 3 files changed, 13 insertions(+), 23 deletions(-) diff --git a/mysql-test/suite/plugins/r/server_audit.result b/mysql-test/suite/plugins/r/server_audit.result index b82b38f4f0a..733b542df19 100644 --- a/mysql-test/suite/plugins/r/server_audit.result +++ b/mysql-test/suite/plugins/r/server_audit.result @@ -261,6 +261,9 @@ A B C D A B C D set global server_audit_query_log_limit= 1024; drop database sa_db; +select length('01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789'); +length('0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456 +2750 set global server_audit_file_path='.'; show status like 'server_audit_current_log'; Variable_name Value @@ -485,6 +488,7 @@ TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,proc, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proc, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,event, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop database sa_db',0 +TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'select length(\'012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_file_path=\'.\'',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'set global server_audit_file_path=\'.\'',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'show status like \'server_audit_current_log\'',0 diff --git a/mysql-test/suite/plugins/t/server_audit.test b/mysql-test/suite/plugins/t/server_audit.test index eba3e5d6770..a70c0b89200 100644 --- a/mysql-test/suite/plugins/t/server_audit.test +++ b/mysql-test/suite/plugins/t/server_audit.test @@ -210,6 +210,8 @@ select 'A', 'B', 'C', 'D'; set global server_audit_query_log_limit= 1024; drop database sa_db; +select length('01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789'); + set global server_audit_file_path='.'; --replace_regex /\.[\\\/]/HOME_DIR\// show status like 'server_audit_current_log'; diff --git a/plugin/server_audit/server_audit.c b/plugin/server_audit/server_audit.c index 666c928d7cc..14f5b2f98b4 100644 --- a/plugin/server_audit/server_audit.c +++ b/plugin/server_audit/server_audit.c @@ -301,8 +301,6 @@ static char logging; static volatile int internal_stop_logging= 0; static char incl_user_buffer[1024]; static char excl_user_buffer[1024]; -static char *big_buffer= NULL; -static size_t big_buffer_alloced= 0; static unsigned int query_log_limit= 0; static char servhost[256]; @@ -555,20 +553,16 @@ static struct st_mysql_show_var audit_status[]= /* These belong to the service initialization */ static PSI_mutex_key key_LOCK_operations; static PSI_mutex_key key_LOCK_atomic; -static PSI_mutex_key key_LOCK_bigbuffer; static PSI_mutex_info mutex_key_list[]= { { &key_LOCK_operations, "SERVER_AUDIT_plugin::lock_operations", PSI_FLAG_GLOBAL}, { &key_LOCK_atomic, "SERVER_AUDIT_plugin::lock_atomic", PSI_FLAG_GLOBAL}, - { &key_LOCK_bigbuffer, "SERVER_AUDIT_plugin::lock_bigbuffer", - PSI_FLAG_GLOBAL} }; #endif static mysql_mutex_t lock_operations; static mysql_mutex_t lock_atomic; -static mysql_mutex_t lock_bigbuffer; /* The Percona server and partly MySQL don't support */ /* launching client errors in the 'update_variable' methods. */ @@ -1700,7 +1694,7 @@ static int log_statement_ex(const struct connection_info *cn, int error_code, const char *type, int take_lock) { size_t csize; - char message_loc[1024]; + char message_loc[2048]; char *message= message_loc; size_t message_size= sizeof(message_loc); char *uh_buffer; @@ -1709,6 +1703,7 @@ static int log_statement_ex(const struct connection_info *cn, unsigned int db_length; long long query_id; int result; + char *big_buffer= NULL; if ((db= cn->db)) db_length= cn->db_length; @@ -1791,17 +1786,9 @@ do_log_query: if (query_len > (message_size - csize)/2) { - flogger_mutex_lock(&lock_bigbuffer); - if (big_buffer_alloced < (query_len * 2 + csize)) - { - big_buffer_alloced= (query_len * 2 + csize + 4095) & ~4095L; - big_buffer= realloc(big_buffer, big_buffer_alloced); - if (big_buffer == NULL) - { - big_buffer_alloced= 0; - return 0; - } - } + size_t big_buffer_alloced= (query_len * 2 + csize + 4095) & ~4095L; + if(!(big_buffer= malloc(big_buffer_alloced))) + return 0; memcpy(big_buffer, message, csize); message= big_buffer; @@ -1846,8 +1833,8 @@ do_log_query: "\',%d", error_code); message[csize]= '\n'; result= write_log(message, csize + 1, take_lock); - if (message == big_buffer) - flogger_mutex_unlock(&lock_bigbuffer); + if (big_buffer) + free(big_buffer); return result; } @@ -2496,7 +2483,6 @@ static int server_audit_init(void *p __attribute__((unused))) #endif flogger_mutex_init(key_LOCK_operations, &lock_operations, MY_MUTEX_INIT_FAST); flogger_mutex_init(key_LOCK_operations, &lock_atomic, MY_MUTEX_INIT_FAST); - flogger_mutex_init(key_LOCK_operations, &lock_bigbuffer, MY_MUTEX_INIT_FAST); coll_init(&incl_user_coll); coll_init(&excl_user_coll); @@ -2581,10 +2567,8 @@ static int server_audit_deinit(void *p __attribute__((unused))) else if (output_type == OUTPUT_SYSLOG) closelog(); - (void) free(big_buffer); flogger_mutex_destroy(&lock_operations); flogger_mutex_destroy(&lock_atomic); - flogger_mutex_destroy(&lock_bigbuffer); error_header(); fprintf(stderr, "STOPPED\n"); -- cgit v1.2.1 From efedf3da68aa0c0a70e0686d9b92c9d0924df098 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Wed, 20 Oct 2021 14:53:01 +0400 Subject: MDEV-22711 Assertion `nr != 0' failed in handler::update_auto_increment. DBUG_ASSERT removed as the AUTO INCREMENT can actually be 0 when the SET insert_id= 0; was done. --- mysql-test/suite/sys_vars/r/insert_id_func.result | 25 +++++++++++++++++++++++ mysql-test/suite/sys_vars/t/insert_id_func.test | 20 ++++++++++++++++++ sql/sys_vars.cc | 18 ++++++++++------ 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/insert_id_func.result b/mysql-test/suite/sys_vars/r/insert_id_func.result index 6a5746e130d..e4486cd5acf 100644 --- a/mysql-test/suite/sys_vars/r/insert_id_func.result +++ b/mysql-test/suite/sys_vars/r/insert_id_func.result @@ -69,3 +69,28 @@ id name drop table t1; disconnect test_con1; disconnect test_con2; +connection default; +CREATE TABLE t1(id int primary key auto_increment); +SET SESSION insert_id=123; +SET SESSION insert_id=0; +INSERT INTO t1 VALUES (); +SET SESSION insert_id=123; +SET SESSION insert_id=default; +INSERT INTO t1 VALUES (); +SET SESSION insert_id=123; +SET SESSION insert_id=-1; +Warnings: +Warning 1292 Truncated incorrect insert_id value: '-1' +INSERT INTO t1 VALUES (); +SET SESSION insert_id=123; +SET SESSION insert_id=-10; +Warnings: +Warning 1292 Truncated incorrect insert_id value: '-10' +INSERT INTO t1 VALUES (); +SELECT * FROM t1; +id +1 +2 +3 +4 +DROP TABLE t1; diff --git a/mysql-test/suite/sys_vars/t/insert_id_func.test b/mysql-test/suite/sys_vars/t/insert_id_func.test index a710afbb0cc..feb510c091b 100644 --- a/mysql-test/suite/sys_vars/t/insert_id_func.test +++ b/mysql-test/suite/sys_vars/t/insert_id_func.test @@ -103,3 +103,23 @@ drop table t1; disconnect test_con1; disconnect test_con2; + +# MDEV-22711 Assertion `nr != 0' failed in handler::update_auto_increment. +# +connection default; +CREATE TABLE t1(id int primary key auto_increment); +SET SESSION insert_id=123; +SET SESSION insert_id=0; +INSERT INTO t1 VALUES (); +SET SESSION insert_id=123; +SET SESSION insert_id=default; +INSERT INTO t1 VALUES (); +SET SESSION insert_id=123; +SET SESSION insert_id=-1; +INSERT INTO t1 VALUES (); +SET SESSION insert_id=123; +SET SESSION insert_id=-10; +INSERT INTO t1 VALUES (); +SELECT * FROM t1; +DROP TABLE t1; + diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index f231f49a667..bd4b2fbb062 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -4064,12 +4064,16 @@ static Sys_var_session_special Sys_identity( */ static bool update_insert_id(THD *thd, set_var *var) { - if (!var->value) - { - my_error(ER_NO_DEFAULT, MYF(0), var->var->name.str); - return true; - } - thd->force_one_auto_inc_interval(var->save_result.ulonglong_value); + /* + If we set the insert_id to the DEFAULT or 0 + it means we 'reset' it so it's value doesn't + affect the INSERT. + */ + if (!var->value || + var->save_result.ulonglong_value == 0) + thd->auto_inc_intervals_forced.empty(); + else + thd->force_one_auto_inc_interval(var->save_result.ulonglong_value); return false; } @@ -4077,6 +4081,8 @@ static ulonglong read_insert_id(THD *thd) { return thd->auto_inc_intervals_forced.minimum(); } + + static Sys_var_session_special Sys_insert_id( "insert_id", "The value to be used by the following INSERT " "or ALTER TABLE statement when inserting an AUTO_INCREMENT value", -- cgit v1.2.1 From 81b8547697f16215be52f4cc2515bcad8c142eaa Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Tue, 26 Oct 2021 15:57:54 +0530 Subject: MDEV-26902 Auxilary fts table evicts during DDL MDEV-25702(commit 696de6d06c0eeaf7b20d5f89278ed7d62a9f204f) should've closed the fts table further. This patch closes the table after finishing the bulk insert operation. --- storage/innobase/row/row0ftsort.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc index c274c63182e..8a3f0243035 100644 --- a/storage/innobase/row/row0ftsort.cc +++ b/storage/innobase/row/row0ftsort.cc @@ -1788,8 +1788,6 @@ row_fts_merge_insert( } exit: - dict_table_close(aux_table, FALSE, FALSE); - fts_sql_commit(trx); trx->op_info = ""; @@ -1799,6 +1797,8 @@ exit: error = ins_ctx.btr_bulk->finish(error); UT_DELETE(ins_ctx.btr_bulk); + dict_table_close(aux_table, FALSE, FALSE); + trx_free_for_background(trx); mem_heap_free(heap); -- cgit v1.2.1 From 6211c35549338c07b766a3671dc0714140a26915 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 19 Oct 2021 11:06:32 +0200 Subject: MDEV-23391 Crash/assertion CREATE OR REPLACE TABLE AS SELECT under LOCK TABLE Happens with Innodb engine. Move unlock_locked_table() past drop_open_table(), and rollback current statement, so that we can actually unlock the table. Anything else results in assertions, in drop, or unlock, or in close_table. --- mysql-test/r/create_or_replace.result | 19 +++++++++++++++++++ mysql-test/t/create_or_replace.test | 19 +++++++++++++++++++ sql/sql_insert.cc | 14 ++++++++------ 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/create_or_replace.result b/mysql-test/r/create_or_replace.result index 54bec5c3f9d..5684843c01c 100644 --- a/mysql-test/r/create_or_replace.result +++ b/mysql-test/r/create_or_replace.result @@ -313,6 +313,25 @@ create table t1 (i int); drop table t1; drop database mysqltest2; # +# MDEV-23391 Server crash in close_thread_table or assertion, upon CREATE OR REPLACE TABLE under lock +# +create table t1 (i int); +lock table t1 write; +select * from information_schema.metadata_lock_info; +THREAD_ID LOCK_MODE LOCK_DURATION LOCK_TYPE TABLE_SCHEMA TABLE_NAME +# MDL_INTENTION_EXCLUSIVE NULL Global read lock +# MDL_INTENTION_EXCLUSIVE NULL Schema metadata lock test +# MDL_SHARED_NO_READ_WRITE NULL Table metadata lock test t1 +create or replace table t1 (a char(1)) engine=Innodb select 'foo' as a; +ERROR 22001: Data too long for column 'a' at row 1 +show tables; +Tables_in_test +t2 +select * from information_schema.metadata_lock_info; +THREAD_ID LOCK_MODE LOCK_DURATION LOCK_TYPE TABLE_SCHEMA TABLE_NAME +create table t1 (i int); +drop table t1; +# # Testing CREATE .. LIKE # create or replace table t1 like t2; diff --git a/mysql-test/t/create_or_replace.test b/mysql-test/t/create_or_replace.test index 4b167663742..ba32f4b7603 100644 --- a/mysql-test/t/create_or_replace.test +++ b/mysql-test/t/create_or_replace.test @@ -251,6 +251,25 @@ create table t1 (i int); drop table t1; drop database mysqltest2; + +--echo # +--echo # MDEV-23391 Server crash in close_thread_table or assertion, upon CREATE OR REPLACE TABLE under lock +--echo # +create table t1 (i int); +lock table t1 write; +--replace_column 1 # +--sorted_result +select * from information_schema.metadata_lock_info; +--error ER_DATA_TOO_LONG +create or replace table t1 (a char(1)) engine=Innodb select 'foo' as a; +show tables; +--replace_column 1 # +--sorted_result +select * from information_schema.metadata_lock_info; +create table t1 (i int); +drop table t1; + + --echo # --echo # Testing CREATE .. LIKE --echo # diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 718682f767e..13dbbaed539 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -4708,12 +4708,6 @@ void select_create::abort_result_set() /* possible error of writing binary log is ignored deliberately */ (void) thd->binlog_flush_pending_rows_event(TRUE, TRUE); - if (create_info->table_was_deleted) - { - /* Unlock locked table that was dropped by CREATE */ - thd->locked_tables_list.unlock_locked_table(thd, - create_info->mdl_ticket); - } if (table) { bool tmp_table= table->s->tmp_table; @@ -4751,5 +4745,13 @@ void select_create::abort_result_set() tmp_table); } } + + if (create_info->table_was_deleted) + { + /* Unlock locked table that was dropped by CREATE. */ + (void) trans_rollback_stmt(thd); + thd->locked_tables_list.unlock_locked_table(thd, create_info->mdl_ticket); + } + DBUG_VOID_RETURN; } -- cgit v1.2.1 From 20848007686e24dbb4283b3b3c5a8acfb32d6ac2 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 19 Oct 2021 11:09:06 +0200 Subject: Try to fix appveyor to prevent occasional failing of mysql_client_test Sometimes, although not often, it would timeout after 3 minutes. --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index f5f1b57735a..b42453a8350 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -25,6 +25,6 @@ test_script: - set PATH=C:\Strawberry\perl\bin;%PATH%;C:\Program Files (x86)\Windows Kits\10\Debuggers\x64 - cd %APPVEYOR_BUILD_FOLDER%\_build\mysql-test - set /A parallel=4*%NUMBER_OF_PROCESSORS% - - perl mysql-test-run.pl --force --max-test-fail=10 --retry=2 -parallel=%parallel% --testcase-timeout=3 --suite=main --skip-test-list=unstable-tests --mysqld=--loose-innodb-flush-log-at-trx-commit=2 + - perl mysql-test-run.pl --force --max-test-fail=10 --retry=2 -parallel=%parallel% --testcase-timeout=4 --suite=main --skip-test-list=unstable-tests --mysqld=--loose-innodb-flush-log-at-trx-commit=2 image: Visual Studio 2019 -- cgit v1.2.1 From 1fb4537e6fe9c1578c2857542fff91e00c0e3292 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Mon, 25 Oct 2021 22:20:29 +0200 Subject: Safemalloc typo fix found by clang. --- mysys/safemalloc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c index 47ba8a0d920..58d4a13e9a6 100644 --- a/mysys/safemalloc.c +++ b/mysys/safemalloc.c @@ -352,9 +352,9 @@ static int sf_sanity() if (count || irem) { warn("Error: Safemalloc link list destroyed"); - return 1; + flag= 1; } - return 0; + return flag; } /** -- cgit v1.2.1 From 1f70e4b00cc6edf695a05a448ff3aff2eee070bb Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Mon, 25 Oct 2021 22:21:27 +0200 Subject: pthread_yield() is depricated now, so use sched_yield() if possible. --- include/my_pthread.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/include/my_pthread.h b/include/my_pthread.h index f369b765edd..be336b00a35 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -289,16 +289,18 @@ void my_pthread_attr_getstacksize(pthread_attr_t *attrib, size_t *size); int my_pthread_mutex_trylock(pthread_mutex_t *mutex); #endif -#if !defined(HAVE_PTHREAD_YIELD_ZERO_ARG) -/* no pthread_yield() available */ #ifdef HAVE_SCHED_YIELD #define pthread_yield() sched_yield() -#elif defined(HAVE_PTHREAD_YIELD_NP) /* can be Mac OS X */ +#else +#if !defined(HAVE_PTHREAD_YIELD_ZERO_ARG) +/* no pthread_yield() available */ +#if defined(HAVE_PTHREAD_YIELD_NP) /* can be Mac OS X */ #define pthread_yield() pthread_yield_np() #elif defined(HAVE_THR_YIELD) #define pthread_yield() thr_yield() -#endif -#endif +#endif //defined(HAVE_PTHREAD_YIELD_NP) +#endif //!defined(HAVE_PTHREAD_YIELD_ZERO_ARG) +#endif //HAVE_SCHED_YIELD /* The defines set_timespec and set_timespec_nsec should be used -- cgit v1.2.1 From d062b69037fd83123337d038508e55e00adbc3cd Mon Sep 17 00:00:00 2001 From: Diego Dupin Date: Tue, 26 Oct 2021 11:01:11 +0200 Subject: MDEV-26868: Session tracking flag in OK_PACKET Take into account client capabilities. --- sql/protocol.cc | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/sql/protocol.cc b/sql/protocol.cc index 1bffcfb3bdb..613668b39a5 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -218,8 +218,6 @@ net_send_ok(THD *thd, NET *net= &thd->net; StringBuffer store; - bool state_changed= false; - bool error= FALSE; DBUG_ENTER("net_send_ok"); @@ -246,6 +244,11 @@ net_send_ok(THD *thd, /* last insert id */ store.q_net_store_length(id); + /* if client has not session tracking capability, don't send state change flag*/ + if (!(thd->client_capabilities & CLIENT_SESSION_TRACK)) { + server_status &= ~SERVER_SESSION_STATE_CHANGED; + } + if (thd->client_capabilities & CLIENT_PROTOCOL_41) { DBUG_PRINT("info", @@ -266,21 +269,17 @@ net_send_ok(THD *thd, } thd->get_stmt_da()->set_overwrite_status(true); - state_changed= - (thd->client_capabilities & CLIENT_SESSION_TRACK) && - (server_status & SERVER_SESSION_STATE_CHANGED); - - if (state_changed || (message && message[0])) + if ((server_status & SERVER_SESSION_STATE_CHANGED) || (message && message[0])) { DBUG_ASSERT(safe_strlen(message) <= MYSQL_ERRMSG_SIZE); store.q_net_store_data((uchar*) safe_str(message), safe_strlen(message)); } - if (unlikely(state_changed)) + if (unlikely(server_status & SERVER_SESSION_STATE_CHANGED)) { store.set_charset(thd->variables.collation_database); - thd->session_tracker.store(thd, &store); + thd->server_status&= ~SERVER_SESSION_STATE_CHANGED; } DBUG_ASSERT(store.length() <= MAX_PACKET_LENGTH); @@ -289,8 +288,6 @@ net_send_ok(THD *thd, if (!error && (!skip_flush || is_eof)) error= net_flush(net); - thd->server_status&= ~SERVER_SESSION_STATE_CHANGED; - thd->get_stmt_da()->set_overwrite_status(false); DBUG_PRINT("info", ("OK sent, so no more error sending allowed")); -- cgit v1.2.1 From 4b8340d89990a8105561888059ec6e3543bed41d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 27 Oct 2021 08:54:06 +0300 Subject: Fix tests for PLUGIN_PARTITION=NO --- mysql-test/suite/mariabackup/partition_partial.test | 1 + mysql-test/t/sp.test | 1 + storage/test_sql_discovery/mysql-test/sql_discovery/simple.test | 1 + 3 files changed, 3 insertions(+) diff --git a/mysql-test/suite/mariabackup/partition_partial.test b/mysql-test/suite/mariabackup/partition_partial.test index 8e288ec997f..7ccc42c036c 100644 --- a/mysql-test/suite/mariabackup/partition_partial.test +++ b/mysql-test/suite/mariabackup/partition_partial.test @@ -1,4 +1,5 @@ #--source include/innodb_page_size.inc +--source include/have_partition.inc # import partitioned table from table from partial backup diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 0ef5e7d0b6e..40a1e873ab9 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -1,3 +1,4 @@ +--source include/have_partition.inc # # Basic stored PROCEDURE tests # diff --git a/storage/test_sql_discovery/mysql-test/sql_discovery/simple.test b/storage/test_sql_discovery/mysql-test/sql_discovery/simple.test index 90eea753a38..a8c7ef9a6bb 100644 --- a/storage/test_sql_discovery/mysql-test/sql_discovery/simple.test +++ b/storage/test_sql_discovery/mysql-test/sql_discovery/simple.test @@ -29,6 +29,7 @@ show warnings; set @@test_sql_discovery_statement='t1:create table t1 (a int primary key) partition by hash(id) partitions 2'; --error ER_SQL_DISCOVER_ERROR select * from t1; +--replace_result 1289 1290 "The 'partitioning' feature is disabled; you need MariaDB built with '--with-plugin-partition' to have it working" "The MariaDB server is running with the --skip-partition option so it cannot execute this statement" show warnings; set @@test_sql_discovery_statement='t1:create table t1 (a int) union=(t3,t4)'; -- cgit v1.2.1 From 2ed148c8d7b0133ecd17377587facadc7e76e9e8 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 27 Oct 2021 10:50:15 +0400 Subject: MDEV-25402 Assertion `!str || str != Ptr' failed in String::copy The assert inside String::copy() prevents copying from from "str" if its own String::Ptr also points to the same memory. The idea of the assert is that copy() performs memory reallocation, and this reallocation can free (and thus invalidate) the memory pointed by Ptr, which can lead to further copying from a freed memory. The assert was incomplete: copy() can free the memory pointed by its Ptr only if String::alloced is true! If the String is not alloced, it is still safe to copy even from the location pointed by Ptr. This scenario demonstrates a safe copy(): const char *tmp= "123"; String str1(tmp, 3); String str2(tmp, 3); // This statement is safe: str2.copy(str1->ptr(), str1->length(), str1->charset(), cs_to, &errors); Inside the copy() the parameter "str" is equal to String::Ptr in this example. But it's still ok to reallocate the memory for str2, because str2 was a constant before the copy() call. Thus reallocation does not make the memory pointed by str1->ptr() invalid. Adjusting the assert condition to allow copying for constant strings. --- mysql-test/r/ctype_utf32_uca.result | 22 ++++++++++++++++++++++ mysql-test/t/ctype_utf32_uca.test | 26 ++++++++++++++++++++++++++ sql/sql_string.cc | 2 +- 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/ctype_utf32_uca.result b/mysql-test/r/ctype_utf32_uca.result index da23fa30ab4..46ca6e7baee 100644 --- a/mysql-test/r/ctype_utf32_uca.result +++ b/mysql-test/r/ctype_utf32_uca.result @@ -7919,5 +7919,27 @@ a b DROP TABLE t1; SET NAMES utf8; # +# MDEV-25402 Assertion `!str || str != Ptr' failed in String::copy +# +SET @c:="SET SESSION collation_connection=utf32_spanish_ci"; +PREPARE s FROM @c; +EXECUTE s; +CREATE PROCEDURE p (IN i INT) EXECUTE s; +SET SESSION character_set_connection=latin1; +SET @c:="SET @b=get_format(DATE,'EUR')"; +PREPARE s FROM @c; +EXECUTE s; +CALL p (@a); +DEALLOCATE PREPARE s; +DROP PROCEDURE p; +SET NAMES utf8; +SET @c:="SET @b=get_format(DATE,'EUR')"; +PREPARE s FROM @c; +EXECUTE s; +SET collation_connection=utf32_spanish_ci; +EXECUTE s; +DEALLOCATE PREPARE s; +SET NAMES utf8; +# # End of 10.2 tests # diff --git a/mysql-test/t/ctype_utf32_uca.test b/mysql-test/t/ctype_utf32_uca.test index 334d8fd1d48..2969480b0ef 100644 --- a/mysql-test/t/ctype_utf32_uca.test +++ b/mysql-test/t/ctype_utf32_uca.test @@ -265,6 +265,32 @@ SET NAMES utf8, collation_connection=utf32_unicode_520_nopad_ci; SET NAMES utf8; +--echo # +--echo # MDEV-25402 Assertion `!str || str != Ptr' failed in String::copy +--echo # + +SET @c:="SET SESSION collation_connection=utf32_spanish_ci"; +PREPARE s FROM @c; +EXECUTE s; +CREATE PROCEDURE p (IN i INT) EXECUTE s; +SET SESSION character_set_connection=latin1; +SET @c:="SET @b=get_format(DATE,'EUR')"; +PREPARE s FROM @c; +EXECUTE s; +CALL p (@a); +DEALLOCATE PREPARE s; +DROP PROCEDURE p; + +SET NAMES utf8; +SET @c:="SET @b=get_format(DATE,'EUR')"; +PREPARE s FROM @c; +EXECUTE s; +SET collation_connection=utf32_spanish_ci; +EXECUTE s; +DEALLOCATE PREPARE s; +SET NAMES utf8; + + --echo # --echo # End of 10.2 tests --echo # diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 4e0c7aea84b..ff6b2163630 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -379,7 +379,7 @@ bool String::copy(const char *str, uint32 arg_length, { uint32 offset; - DBUG_ASSERT(!str || str != Ptr); + DBUG_ASSERT(!str || str != Ptr || !alloced); if (!needs_conversion(arg_length, from_cs, to_cs, &offset)) { -- cgit v1.2.1 From 3a9967d7579a31e5a43606d563584335348caaa5 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Wed, 27 Oct 2021 10:13:56 +0300 Subject: Fix compile warning: ha_rocksdb.h:459:15: warning: 'table_type' overrides a member function but is not marked 'override' [-Winconsistent-missing-override] --- storage/rocksdb/ha_rocksdb.h | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/storage/rocksdb/ha_rocksdb.h b/storage/rocksdb/ha_rocksdb.h index 437c8667994..4a379cd638a 100644 --- a/storage/rocksdb/ha_rocksdb.h +++ b/storage/rocksdb/ha_rocksdb.h @@ -448,15 +448,13 @@ class ha_rocksdb : public my_core::handler { } } - /** @brief - The name that will be used for display purposes. - */ - const char *table_type() const /*override*/ { - DBUG_ENTER_FUNC(); - // MariaDB: this function is not virtual, however ha_innodb - // declares it (and then never uses!) psergey-merge-todo:. - DBUG_RETURN(rocksdb_hton_name); - } + /* + MariaDB: this function: + + const char *table_type() const + + is non-virtual in class handler, so there's no point to override it. + */ /* The following is only used by SHOW KEYS: */ const char *index_type(uint inx) override { -- cgit v1.2.1 From 1f5ca66e53b165c29ea733acd0fab79975a43eda Mon Sep 17 00:00:00 2001 From: Nikita Malyavin Date: Wed, 27 Oct 2021 18:37:33 +0300 Subject: =?UTF-8?q?MDEV-26866=20FOREIGN=20KEY=E2=80=A6SET=20NULL=20corrupt?= =?UTF-8?q?s=20an=20index=20on=20a=20virtual=20column?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The initial test case for MySQL Bug #33053297 is based on mysql/mysql-server@27130e25078864b010d81266f9613d389d4a229b. innobase_get_field_from_update_vector is not a suitable function to fetch updated row info, as well as parent table's update vector is not always suitable. For instance, in case of DELETE it contains undefined data. castade->update vector seems to be good enough to fetch all base columns update data, and besides faster, and less error-prone. --- mysql-test/suite/gcol/r/innodb_virtual_fk.result | 200 +++++++++++++++++++++++ mysql-test/suite/gcol/t/innodb_virtual_fk.test | 184 +++++++++++++++++++++ storage/innobase/handler/ha_innodb.cc | 64 ++------ storage/innobase/include/row0mysql.h | 10 +- storage/innobase/row/row0ins.cc | 15 +- storage/innobase/row/row0merge.cc | 4 +- storage/innobase/row/row0sel.cc | 2 +- storage/innobase/row/row0upd.cc | 5 +- storage/innobase/row/row0vers.cc | 2 +- 9 files changed, 415 insertions(+), 71 deletions(-) diff --git a/mysql-test/suite/gcol/r/innodb_virtual_fk.result b/mysql-test/suite/gcol/r/innodb_virtual_fk.result index 367ed1223f7..de61c16f739 100644 --- a/mysql-test/suite/gcol/r/innodb_virtual_fk.result +++ b/mysql-test/suite/gcol/r/innodb_virtual_fk.result @@ -826,3 +826,203 @@ DROP TABLE email_stats; DROP TABLE emails_metadata; DROP TABLE emails; DROP DATABASE `a-b`; +USE test; +# +# Bug#33053297 VIRTUAL INDEX CORRUPTED DURING CASCADE UPDATE ON CHILD TABLE +# +# Test-Case 1 +CREATE TABLE emails ( +id int unsigned NOT NULL AUTO_INCREMENT, +PRIMARY KEY (id) +) ENGINE=InnoDB; +CREATE TABLE email_stats ( +id bigint unsigned NOT NULL AUTO_INCREMENT, +email_id int unsigned DEFAULT NULL, +date_sent datetime NOT NULL, +generated_sent_date date GENERATED ALWAYS AS +(concat(year(date_sent), '-', lpad(month(date_sent), 2, '0'), +'-', lpad(dayofmonth(date_sent), 2, '0'))), +PRIMARY KEY (id), +KEY IDX_ES1 (email_id), +KEY mautic_generated_sent_date_email_id(generated_sent_date, email_id), +FOREIGN KEY (email_id) REFERENCES emails (id) ON DELETE SET NULL +) ENGINE = InnoDB; +INSERT INTO emails VALUES (1); +INSERT INTO email_stats (id, email_id, date_sent) +VALUES (1, 1, '2020-10-22 13:32:41'); +SELECT * FROM email_stats; +id email_id date_sent generated_sent_date +1 1 2020-10-22 13:32:41 2020-10-22 +DELETE FROM emails; +DELETE FROM email_stats; +# Clean up. +DROP TABLE email_stats; +DROP TABLE emails; +# Test-Case 2 +CREATE TABLE emails ( +id int unsigned NOT NULL AUTO_INCREMENT, +PRIMARY KEY (id) +) ENGINE = InnoDB +DEFAULT CHARSET = utf8mb4 +COLLATE = utf8mb4_unicode_ci +ROW_FORMAT = DYNAMIC; +CREATE TABLE email_stats ( +id bigint unsigned NOT NULL AUTO_INCREMENT, +email_id int unsigned DEFAULT NULL, +date_sent datetime NOT NULL, +generated_sent_date date GENERATED ALWAYS AS +(concat(year(date_sent), '-', lpad(month(date_sent), 2, '0'), +'-', lpad(dayofmonth(date_sent), 2, '0'))), +PRIMARY KEY (id), +KEY IDX_ES1 (email_id), +KEY mautic_generated_sent_date_email_id(generated_sent_date, email_id), +FOREIGN KEY (email_id) REFERENCES emails (id) +ON DELETE SET NULL +ON UPDATE SET NULL +) ENGINE = InnoDB; +INSERT INTO emails VALUES (1); +INSERT INTO email_stats (id, email_id, date_sent) +VALUES (1, 1, '2020-10-22 13:32:41'); +UPDATE emails SET id = 2 where id = 1; +SELECT id FROM email_stats WHERE generated_sent_date IS NULL; +id +SELECT * FROM email_stats; +id email_id date_sent generated_sent_date +1 NULL 2020-10-22 13:32:41 2020-10-22 +UPDATE email_stats +SET email_id=2 +WHERE DATE(generated_sent_date) = '2020-10-22'; +SELECT * FROM email_stats; +id email_id date_sent generated_sent_date +1 2 2020-10-22 13:32:41 2020-10-22 +# Clean up. +DROP TABLE email_stats; +DROP TABLE emails; +# Test-case 3 +CREATE TABLE emails ( +id int unsigned NOT NULL AUTO_INCREMENT, +PRIMARY KEY (id) +) ENGINE = INNODB +DEFAULT CHARSET = utf8mb4 +COLLATE = utf8mb4_unicode_ci +ROW_FORMAT = DYNAMIC; +CREATE TABLE email_stats ( +id bigint unsigned NOT NULL AUTO_INCREMENT, +email_id int unsigned DEFAULT NULL, +date_sent datetime NOT NULL, +generated_sent_email varchar(20) GENERATED ALWAYS AS +(CONCAT(YEAR(date_sent), '-', COALESCE(email_id, '$'))), +PRIMARY KEY (id), +KEY idx_es1 (email_id), +KEY mautic_generated_sent_date_email(generated_sent_email, email_id), +FOREIGN KEY (email_id) REFERENCES emails (id) ON DELETE SET NULL +) ENGINE = INNODB; +INSERT INTO emails VALUES (1); +INSERT INTO email_stats (id, email_id, date_sent) +VALUES (1, 1, '2020-10-22 13:32:41'); +SELECT * FROM email_stats; +id email_id date_sent generated_sent_email +1 1 2020-10-22 13:32:41 2020-1 +SELECT date_sent FROM email_stats WHERE generated_sent_email = '2020-1'; +date_sent +2020-10-22 13:32:41 +DELETE FROM emails; +SELECT * FROM email_stats; +id email_id date_sent generated_sent_email +1 NULL 2020-10-22 13:32:41 2020-$ +SELECT date_sent FROM email_stats WHERE generated_sent_email = '2020-$'; +date_sent +2020-10-22 13:32:41 +# Clean up. +DROP TABLE email_stats; +DROP TABLE emails; +# Test-case 4 +CREATE TABLE emails ( +id int unsigned NOT NULL AUTO_INCREMENT, +PRIMARY KEY (id) +) ENGINE = INNODB; +CREATE TABLE email_stats ( +id bigint unsigned NOT NULL AUTO_INCREMENT, +email_id int unsigned DEFAULT NULL, +date_sent datetime NOT NULL, +generated_sent_email varchar(20) GENERATED ALWAYS AS +(CONCAT(YEAR(date_sent), '-', COALESCE(email_id, '$'))), +PRIMARY KEY (id), +KEY idx_es1 (email_id), +KEY mautic_generated_sent_date_email(generated_sent_email, email_id), +FOREIGN KEY (email_id) REFERENCES emails (id) ON UPDATE SET NULL +) ENGINE = INNODB; +INSERT INTO emails VALUES (1); +INSERT INTO email_stats (id, email_id, date_sent) +VALUES (1, 1, '2020-10-22 13:32:41'); +SELECT * FROM email_stats; +id email_id date_sent generated_sent_email +1 1 2020-10-22 13:32:41 2020-1 +SELECT date_sent FROM email_stats WHERE generated_sent_email = '2020-1'; +date_sent +2020-10-22 13:32:41 +UPDATE emails SET id = 2 WHERE id = 1; +SELECT * FROM email_stats; +id email_id date_sent generated_sent_email +1 NULL 2020-10-22 13:32:41 2020-$ +SELECT date_sent FROM email_stats WHERE generated_sent_email = '2020-$'; +date_sent +2020-10-22 13:32:41 +DROP TABLE email_stats; +DROP TABLE emails; +CREATE TABLE emails (breaker int unsigned, +KEY (breaker), +id int unsigned NOT NULL AUTO_INCREMENT, +PRIMARY KEY (id) +) ENGINE=INNODB; +CREATE TABLE email_stats ( +id bigint unsigned NOT NULL AUTO_INCREMENT, +email_id int unsigned DEFAULT NULL, +date_sent datetime NOT NULL, +generated_sent_email varchar(20) GENERATED ALWAYS AS +(CONCAT(YEAR(date_sent), +'-', +COALESCE(email_id, '$'))), +PRIMARY KEY (id), +KEY idx_es1 (email_id), +KEY mautic_generated_sent_date_email (generated_sent_email, email_id), +FOREIGN KEY fk_ea1 (email_id) REFERENCES emails (breaker) +ON DELETE SET NULL +) ENGINE=INNODB; +show create table email_stats; +Table Create Table +email_stats CREATE TABLE `email_stats` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `email_id` int(10) unsigned DEFAULT NULL, + `date_sent` datetime NOT NULL, + `generated_sent_email` varchar(20) GENERATED ALWAYS AS (concat(year(`date_sent`),'-',coalesce(`email_id`,'$'))) VIRTUAL, + PRIMARY KEY (`id`), + KEY `idx_es1` (`email_id`), + KEY `mautic_generated_sent_date_email` (`generated_sent_email`,`email_id`), + CONSTRAINT `fk_ea1` FOREIGN KEY (`email_id`) REFERENCES `emails` (`breaker`) ON DELETE SET NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +INSERT INTO emails VALUES (1,1); +INSERT INTO email_stats(id, email_id, date_sent) +VALUES (1, 1, '2020-10-22 13:32:41'); +SELECT * FROM email_stats; +id email_id date_sent generated_sent_email +1 1 2020-10-22 13:32:41 2020-1 +SELECT date_sent FROM email_stats WHERE generated_sent_email = '2020-1'; +date_sent +2020-10-22 13:32:41 +DELETE FROM emails; +SELECT * FROM email_stats; +id email_id date_sent generated_sent_email +1 NULL 2020-10-22 13:32:41 2020-$ +SELECT date_sent +FROM email_stats force index (mautic_generated_sent_date_email) +WHERE generated_sent_email = '2020-$'; +date_sent +2020-10-22 13:32:41 +SELECT date_sent +FROM email_stats force index (idx_es1) +WHERE generated_sent_email = '2020-$'; +date_sent +2020-10-22 13:32:41 +DROP TABLE email_stats; +DROP TABLE emails; diff --git a/mysql-test/suite/gcol/t/innodb_virtual_fk.test b/mysql-test/suite/gcol/t/innodb_virtual_fk.test index c99259531b3..0f0406b5dd4 100644 --- a/mysql-test/suite/gcol/t/innodb_virtual_fk.test +++ b/mysql-test/suite/gcol/t/innodb_virtual_fk.test @@ -693,3 +693,187 @@ DROP TABLE email_stats; DROP TABLE emails_metadata; DROP TABLE emails; DROP DATABASE `a-b`; +USE test; + +--echo # +--echo # Bug#33053297 VIRTUAL INDEX CORRUPTED DURING CASCADE UPDATE ON CHILD TABLE +--echo # + +--echo # Test-Case 1 +CREATE TABLE emails ( + id int unsigned NOT NULL AUTO_INCREMENT, + PRIMARY KEY (id) +) ENGINE=InnoDB; + +CREATE TABLE email_stats ( + id bigint unsigned NOT NULL AUTO_INCREMENT, + email_id int unsigned DEFAULT NULL, + date_sent datetime NOT NULL, + generated_sent_date date GENERATED ALWAYS AS + (concat(year(date_sent), '-', lpad(month(date_sent), 2, '0'), + '-', lpad(dayofmonth(date_sent), 2, '0'))), + PRIMARY KEY (id), + KEY IDX_ES1 (email_id), + KEY mautic_generated_sent_date_email_id(generated_sent_date, email_id), + FOREIGN KEY (email_id) REFERENCES emails (id) ON DELETE SET NULL +) ENGINE = InnoDB; + +INSERT INTO emails VALUES (1); +INSERT INTO email_stats (id, email_id, date_sent) + VALUES (1, 1, '2020-10-22 13:32:41'); +SELECT * FROM email_stats; + +DELETE FROM emails; +DELETE FROM email_stats; + +--echo # Clean up. +DROP TABLE email_stats; +DROP TABLE emails; + +--echo # Test-Case 2 +CREATE TABLE emails ( + id int unsigned NOT NULL AUTO_INCREMENT, + PRIMARY KEY (id) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_unicode_ci + ROW_FORMAT = DYNAMIC; + +CREATE TABLE email_stats ( + id bigint unsigned NOT NULL AUTO_INCREMENT, + email_id int unsigned DEFAULT NULL, + date_sent datetime NOT NULL, + generated_sent_date date GENERATED ALWAYS AS + (concat(year(date_sent), '-', lpad(month(date_sent), 2, '0'), + '-', lpad(dayofmonth(date_sent), 2, '0'))), + PRIMARY KEY (id), + KEY IDX_ES1 (email_id), + KEY mautic_generated_sent_date_email_id(generated_sent_date, email_id), + FOREIGN KEY (email_id) REFERENCES emails (id) + ON DELETE SET NULL + ON UPDATE SET NULL +) ENGINE = InnoDB; + +INSERT INTO emails VALUES (1); +INSERT INTO email_stats (id, email_id, date_sent) + VALUES (1, 1, '2020-10-22 13:32:41'); + +UPDATE emails SET id = 2 where id = 1; + +SELECT id FROM email_stats WHERE generated_sent_date IS NULL; +SELECT * FROM email_stats; +UPDATE email_stats + SET email_id=2 + WHERE DATE(generated_sent_date) = '2020-10-22'; +SELECT * FROM email_stats; + +--echo # Clean up. +DROP TABLE email_stats; +DROP TABLE emails; + +--echo # Test-case 3 +CREATE TABLE emails ( + id int unsigned NOT NULL AUTO_INCREMENT, + PRIMARY KEY (id) +) ENGINE = INNODB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_unicode_ci + ROW_FORMAT = DYNAMIC; +CREATE TABLE email_stats ( + id bigint unsigned NOT NULL AUTO_INCREMENT, + email_id int unsigned DEFAULT NULL, + date_sent datetime NOT NULL, + generated_sent_email varchar(20) GENERATED ALWAYS AS + (CONCAT(YEAR(date_sent), '-', COALESCE(email_id, '$'))), + PRIMARY KEY (id), + KEY idx_es1 (email_id), + KEY mautic_generated_sent_date_email(generated_sent_email, email_id), + FOREIGN KEY (email_id) REFERENCES emails (id) ON DELETE SET NULL +) ENGINE = INNODB; + +INSERT INTO emails VALUES (1); +INSERT INTO email_stats (id, email_id, date_sent) + VALUES (1, 1, '2020-10-22 13:32:41'); +SELECT * FROM email_stats; +SELECT date_sent FROM email_stats WHERE generated_sent_email = '2020-1'; + +DELETE FROM emails; + +SELECT * FROM email_stats; +SELECT date_sent FROM email_stats WHERE generated_sent_email = '2020-$'; + +--echo # Clean up. +DROP TABLE email_stats; +DROP TABLE emails; + +--echo # Test-case 4 +CREATE TABLE emails ( + id int unsigned NOT NULL AUTO_INCREMENT, + PRIMARY KEY (id) +) ENGINE = INNODB; + +CREATE TABLE email_stats ( + id bigint unsigned NOT NULL AUTO_INCREMENT, + email_id int unsigned DEFAULT NULL, + date_sent datetime NOT NULL, + generated_sent_email varchar(20) GENERATED ALWAYS AS + (CONCAT(YEAR(date_sent), '-', COALESCE(email_id, '$'))), + PRIMARY KEY (id), + KEY idx_es1 (email_id), + KEY mautic_generated_sent_date_email(generated_sent_email, email_id), + FOREIGN KEY (email_id) REFERENCES emails (id) ON UPDATE SET NULL +) ENGINE = INNODB; + +INSERT INTO emails VALUES (1); +INSERT INTO email_stats (id, email_id, date_sent) + VALUES (1, 1, '2020-10-22 13:32:41'); +SELECT * FROM email_stats; +SELECT date_sent FROM email_stats WHERE generated_sent_email = '2020-1'; + +UPDATE emails SET id = 2 WHERE id = 1; + +SELECT * FROM email_stats; +SELECT date_sent FROM email_stats WHERE generated_sent_email = '2020-$'; + +#clean up. +DROP TABLE email_stats; +DROP TABLE emails; + +CREATE TABLE emails (breaker int unsigned, + KEY (breaker), + id int unsigned NOT NULL AUTO_INCREMENT, + PRIMARY KEY (id) +) ENGINE=INNODB; + +CREATE TABLE email_stats ( + id bigint unsigned NOT NULL AUTO_INCREMENT, + email_id int unsigned DEFAULT NULL, + date_sent datetime NOT NULL, + generated_sent_email varchar(20) GENERATED ALWAYS AS + (CONCAT(YEAR(date_sent), + '-', + COALESCE(email_id, '$'))), + PRIMARY KEY (id), + KEY idx_es1 (email_id), + KEY mautic_generated_sent_date_email (generated_sent_email, email_id), + FOREIGN KEY fk_ea1 (email_id) REFERENCES emails (breaker) + ON DELETE SET NULL +) ENGINE=INNODB; + +show create table email_stats; +INSERT INTO emails VALUES (1,1); +INSERT INTO email_stats(id, email_id, date_sent) + VALUES (1, 1, '2020-10-22 13:32:41'); +SELECT * FROM email_stats; +SELECT date_sent FROM email_stats WHERE generated_sent_email = '2020-1'; +DELETE FROM emails; +SELECT * FROM email_stats; +SELECT date_sent + FROM email_stats force index (mautic_generated_sent_date_email) + WHERE generated_sent_email = '2020-$'; +SELECT date_sent + FROM email_stats force index (idx_es1) + WHERE generated_sent_email = '2020-$'; + +DROP TABLE email_stats; +DROP TABLE emails; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 91d245ad0e2..37748cb497a 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -21795,48 +21795,6 @@ innobase_rename_vc_templ( table->vc_templ->tb_name = t_tbname; } -/** Get the updated parent field value from the update vector for the -given col_no. -@param[in] foreign foreign key information -@param[in] update updated parent vector. -@param[in] col_no base column position of the child table to check -@return updated field from the parent update vector, else NULL */ -static -dfield_t* -innobase_get_field_from_update_vector( - dict_foreign_t* foreign, - upd_t* update, - ulint col_no) -{ - dict_table_t* parent_table = foreign->referenced_table; - dict_index_t* parent_index = foreign->referenced_index; - ulint parent_field_no; - ulint parent_col_no; - ulint prefix_col_no; - - for (ulint i = 0; i < foreign->n_fields; i++) { - if (dict_index_get_nth_col_no(foreign->foreign_index, i) - != col_no) { - continue; - } - - parent_col_no = dict_index_get_nth_col_no(parent_index, i); - parent_field_no = dict_table_get_nth_col_pos( - parent_table, parent_col_no, &prefix_col_no); - - for (ulint j = 0; j < update->n_fields; j++) { - upd_field_t* parent_ufield - = &update->fields[j]; - - if (parent_ufield->field_no == parent_field_no) { - return(&parent_ufield->new_val); - } - } - } - - return (NULL); -} - /** Allocate a heap and record for calculating virtual fields @@ -21919,9 +21877,10 @@ void innobase_report_computed_value_failed(dtuple_t *row) @param[in] ifield index field @param[in] thd MySQL thread handle @param[in,out] mysql_table mysql table object +@param[in,out] mysql_rec MariaDB record buffer @param[in] old_table during ALTER TABLE, this is the old table or NULL. -@param[in] parent_update update vector for the parent row +@param[in] update update vector for the row, if any @param[in] foreign foreign key information @return the field filled with computed value, or NULL if just want to store the value in passed in "my_rec" */ @@ -21937,8 +21896,7 @@ innobase_get_computed_value( TABLE* mysql_table, byte* mysql_rec, const dict_table_t* old_table, - upd_t* parent_update, - dict_foreign_t* foreign) + const upd_t* update) { byte rec_buf2[REC_VERSION_56_MAX_INDEX_COL_LEN]; byte* buf; @@ -21951,6 +21909,8 @@ innobase_get_computed_value( ulint ret = 0; + dict_index_t *clust_index= dict_table_get_first_index(index->table); + ut_ad(index->table->vc_templ); ut_ad(thd != NULL); ut_ad(mysql_table); @@ -21980,14 +21940,16 @@ innobase_get_computed_value( = index->table->vc_templ->vtempl[col_no]; const byte* data; - if (parent_update != NULL) { - /** Get the updated field from update vector - of the parent table. */ - row_field = innobase_get_field_from_update_vector( - foreign, parent_update, col_no); + if (update) { + ulint clust_no = dict_col_get_clust_pos(base_col, + clust_index); + if (const upd_field_t *uf = upd_get_field_by_field_no( + update, clust_no, false)) { + row_field = &uf->new_val; + } } - if (row_field == NULL) { + if (!row_field) { row_field = dtuple_get_nth_field(row, col_no); } diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h index 8738f991368..5faae86f5be 100644 --- a/storage/innobase/include/row0mysql.h +++ b/storage/innobase/include/row0mysql.h @@ -881,11 +881,12 @@ void innobase_report_computed_value_failed(dtuple_t *row); @param[in,out] local_heap heap memory for processing large data etc. @param[in,out] heap memory heap that copies the actual index row @param[in] ifield index field -@param[in] thd MySQL thread handle -@param[in,out] mysql_table mysql table object +@param[in] thd connection handle +@param[in,out] mysql_table MariaDB table handle +@param[in,out] mysql_rec MariaDB record buffer @param[in] old_table during ALTER TABLE, this is the old table or NULL. -@param[in] parent_update update vector for the parent row +@param[in] update update vector for the parent row @param[in] foreign foreign key information @return the field filled with computed value */ dfield_t* @@ -900,8 +901,7 @@ innobase_get_computed_value( TABLE* mysql_table, byte* mysql_rec, const dict_table_t* old_table, - upd_t* parent_update, - dict_foreign_t* foreign); + const upd_t* update); /** Get the computed value by supplying the base column values. @param[in,out] table the table whose virtual column diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 929d3683ce6..cbe6577c02a 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -898,7 +898,6 @@ row_ins_invalidate_query_cache( innobase_invalidate_query_cache(thr_get_trx(thr), name, len); } - /** Fill virtual column information in cascade node for the child table. @param[out] cascade child update node @param[in] rec clustered rec of child table @@ -945,6 +944,11 @@ row_ins_foreign_fill_virtual( if (!record) { return DB_OUT_OF_MEMORY; } + ut_ad(!node->is_delete + || (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)); + ut_ad(foreign->type & (DICT_FOREIGN_ON_DELETE_SET_NULL + | DICT_FOREIGN_ON_UPDATE_SET_NULL + | DICT_FOREIGN_ON_UPDATE_CASCADE)); for (ulint i = 0; i < n_v_fld; i++) { @@ -960,7 +964,7 @@ row_ins_foreign_fill_virtual( dfield_t* vfield = innobase_get_computed_value( update->old_vrow, col, index, &vc.heap, update->heap, NULL, thd, mysql_table, - record, NULL, NULL, NULL); + record, NULL, NULL); if (vfield == NULL) { return DB_COMPUTE_VALUE_FAILED; @@ -976,16 +980,11 @@ row_ins_foreign_fill_virtual( upd_field_set_v_field_no(upd_field, i, index); - bool set_null = - node->is_delete - ? (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) - : (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL); - dfield_t* new_vfield = innobase_get_computed_value( update->old_vrow, col, index, &vc.heap, update->heap, NULL, thd, mysql_table, record, NULL, - set_null ? update : node->update, foreign); + update); if (new_vfield == NULL) { return DB_COMPUTE_VALUE_FAILED; diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 9e6179585b1..faa148cca24 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -600,8 +600,8 @@ error: row_field = innobase_get_computed_value( row, v_col, clust_index, v_heap, NULL, ifield, trx->mysql_thd, - my_table, vcol_storage.innobase_record, - old_table, NULL, NULL); + my_table, vcol_storage.innobase_record, + old_table, NULL); if (row_field == NULL) { *err = DB_COMPUTE_VALUE_FAILED; diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 83bf18ab9b8..87c67edff4b 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -328,7 +328,7 @@ row_sel_sec_rec_is_for_clust_rec( &heap, NULL, NULL, thr_get_trx(thr)->mysql_thd, thr->prebuilt->m_mysql_table, - record, NULL, NULL, NULL); + record, NULL, NULL); if (vfield == NULL) { innobase_report_computed_value_failed(row); diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index a58c3993e90..0a79225da8c 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -1149,7 +1149,7 @@ row_upd_build_difference_binary( dfield_t* vfield = innobase_get_computed_value( update->old_vrow, col, index, &vc.heap, heap, NULL, thd, mysql_table, record, - NULL, NULL, NULL); + NULL, NULL); if (vfield == NULL) { *error = DB_COMPUTE_VALUE_FAILED; return(NULL); @@ -2175,8 +2175,7 @@ row_upd_store_v_row( node->row, col, index, &vc.heap, node->heap, NULL, thd, mysql_table, - record, NULL, NULL, - NULL); + record, NULL, NULL); if (vfield == NULL) { return false; } diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc index b9bc8418366..bf229966525 100644 --- a/storage/innobase/row/row0vers.cc +++ b/storage/innobase/row/row0vers.cc @@ -491,7 +491,7 @@ row_vers_build_clust_v_col( dfield_t *vfield = innobase_get_computed_value( row, col, clust_index, &vc.heap, heap, NULL, thd, maria_table, record, NULL, - NULL, NULL); + NULL); if (vfield == NULL) { innobase_report_computed_value_failed(row); ut_ad(0); -- cgit v1.2.1 From 563daec123728f69dc56d898d1d8b198e9e2d411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 28 Oct 2021 07:35:49 +0300 Subject: MDEV-26867: Update the InnoDB version number to 5.7.36 The InnoDB changes in MySQL 5.7.36 that were applicable to MariaDB were covered by MDEV-26864, MDEV-26865, MDEV-26866. --- storage/innobase/include/univ.i | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index d302770b230..fb1f5b705aa 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -41,7 +41,7 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_MAJOR 5 #define INNODB_VERSION_MINOR 7 -#define INNODB_VERSION_BUGFIX 35 +#define INNODB_VERSION_BUGFIX 36 /* The following is the InnoDB version as shown in SELECT plugin_version FROM information_schema.plugins; -- cgit v1.2.1