From 5f533035d3ad8dc56ef339196633a931d7bff60c Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Thu, 6 Aug 2015 17:46:47 +0200 Subject: [PATCH 01/67] Fix the TDBDOS::EstimatedLength function that was wrongly counting its calculation virtual and special columns. modified: storage/connect/reldef.h modified: storage/connect/tabdos.cpp --- storage/connect/reldef.h | 3 ++- storage/connect/tabdos.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/storage/connect/reldef.h b/storage/connect/reldef.h index 4aa29037dfc..dada5716dbe 100644 --- a/storage/connect/reldef.h +++ b/storage/connect/reldef.h @@ -193,7 +193,8 @@ class DllExport COLDEF : public COLCRT { /* Column description block friend class COLBLK; friend class DBFFAM; friend class TDBASE; - public: + friend class TDBDOS; +public: COLDEF(void); // Constructor // Implementation diff --git a/storage/connect/tabdos.cpp b/storage/connect/tabdos.cpp index a1e58ab3344..527fe55dd89 100644 --- a/storage/connect/tabdos.cpp +++ b/storage/connect/tabdos.cpp @@ -2018,7 +2018,8 @@ int TDBDOS::EstimatedLength(void) // result if we set dep to 1 dep = 1 + cdp->GetLong() / 20; // Why 20 ????? } else for (; cdp; cdp = cdp->GetNext()) - dep = MY_MAX(dep, cdp->GetOffset()); + if (!(cdp->Flags & (U_VIRTUAL|U_SPECIAL))) + dep = MY_MAX(dep, cdp->GetOffset()); return (int)dep; } // end of Estimated Length From 335ec7a363ffc49c5c974d45782220bf4977d846 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Tue, 11 Aug 2015 21:15:33 +0200 Subject: [PATCH 02/67] Prevent wrong update of expanded columns when pretty is not 2. modified: storage/connect/tabjson.cpp --- storage/connect/tabjson.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index fafba6228b9..211a58f0344 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -755,7 +755,7 @@ int TDBJSN::MakeTopTree(PGLOBAL g, PJSON jsp) } else strcpy(To_Line, s); - Row->Clear(); +// Row->Clear(); return false; } else return true; @@ -979,7 +979,8 @@ bool JSONCOL::ParseJpath(PGLOBAL g) if (!stricmp(Name, colp->GetName())) { Nod = colp->Nod; Nodes = colp->Nodes; - goto fin; + Xpd = colp->Xpd; + goto fin; } // endif Name sprintf(g->Message, "Cannot parse updated column %s", Name); @@ -1347,7 +1348,12 @@ PJSON JSONCOL::GetRow(PGLOBAL g) /***********************************************************************/ void JSONCOL::WriteColumn(PGLOBAL g) { - /*********************************************************************/ + if (Xpd && Tjp->Pretty < 2) { + strcpy(g->Message, "Cannot write expanded column when Pretty is not 2"); + longjmp(g->jumper[g->jump_level], 666); + } // endif Xpd + + /*********************************************************************/ /* Check whether this node must be written. */ /*********************************************************************/ if (Value != To_Val) From 6d46c977a71a526ee7307b4bd6393ea122e21989 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Fri, 14 Aug 2015 14:23:14 +0200 Subject: [PATCH 03/67] Fix crash when SetValue_char is called with a negative length value. This can happen in odbconn.cpp when SQLFetch returns SQL_NO_TOTAL (-4) as length. modified: storage/connect/odbconn.cpp modified: storage/connect/value.cpp --- storage/connect/odbconn.cpp | 6 ++++-- storage/connect/value.cpp | 22 +++++++++++++--------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp index 6aaa048de81..1ccdf231970 100644 --- a/storage/connect/odbconn.cpp +++ b/storage/connect/odbconn.cpp @@ -2360,9 +2360,11 @@ int ODBConn::GetCatInfo(CATPARM *cap) } // endif rc for (n = 0, crp = qrp->Colresp; crp; n++, crp = crp->Next) { - if (vlen[n] == SQL_NULL_DATA) + if (vlen[n] == SQL_NO_TOTAL) + ThrowDBX("Unexpected SQL_NO_TOTAL returned from SQLFetch"); + else if (vlen[n] == SQL_NULL_DATA) pval[n]->SetNull(true); - else if (crp->Type == TYPE_STRING && vlen[n] != SQL_NULL_DATA) + else if (crp->Type == TYPE_STRING/* && vlen[n] != SQL_NULL_DATA*/) pval[n]->SetValue_char(pbuf[n], vlen[n]); else pval[n]->SetNull(false); diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp index 03ec0eb8e40..884ce976a52 100644 --- a/storage/connect/value.cpp +++ b/storage/connect/value.cpp @@ -103,6 +103,7 @@ ulonglong CharToNumber(char *p, int n, ulonglong maxval, if (minus) *minus = false; if (rc) *rc = false; + if (n <= 0) return 0LL; // Eliminate leading blanks or 0 for (p2 = p + n; p < p2 && (*p == ' ' || *p == '0'); p++) ; @@ -705,7 +706,7 @@ bool TYPVAL::SetValue_char(char *p, int n) template <> bool TYPVAL::SetValue_char(char *p, int n) { - if (p) { + if (p && n > 0) { char buf[64]; for (; n > 0 && *p == ' '; p++) @@ -1345,7 +1346,7 @@ bool TYPVAL::SetValue_char(char *p, int n) { bool rc; - if (p) { + if (p && n > 0) { rc = n > Len; if ((n = MY_MIN(n, Len))) { @@ -1804,7 +1805,7 @@ bool DECVAL::SetValue_char(char *p, int n) { bool rc; - if (p) { + if (p && n > 0) { rc = n > Len; if ((n = MY_MIN(n, Len))) { @@ -2095,7 +2096,7 @@ bool BINVAL::SetValue_char(char *p, int n) { bool rc; - if (p) { + if (p && n > 0) { rc = n > Clen; Len = MY_MIN(n, Clen); memcpy(Binp, p, Len); @@ -2672,13 +2673,16 @@ bool DTVAL::SetValue_char(char *p, int n) int ndv; int dval[6]; - // Trim trailing blanks - for (p2 = p + n -1; p < p2 && *p2 == ' '; p2--) ; + if (n > 0) { + // Trim trailing blanks + for (p2 = p + n -1; p < p2 && *p2 == ' '; p2--); - if ((rc = (n = p2 - p + 1) > Len)) - n = Len; + if ((rc = (n = p2 - p + 1) > Len)) + n = Len; + + memcpy(Sdate, p, n); + } // endif n - memcpy(Sdate, p, n); Sdate[n] = '\0'; ndv = ExtractDate(Sdate, Pdtp, DefYear, dval); From e939ea58e511e7a3cca315923188fda2cfd7477b Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Wed, 9 Sep 2015 01:26:00 +0200 Subject: [PATCH 04/67] Fix assert error for where clause with UDF's was fixed in HA_CONNECT::CondFilter moving pval->val_str(&tmp) modified: storage/connect/ha_connect.cc --- storage/connect/ha_connect.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 007b2428094..c502493357e 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -2486,9 +2486,6 @@ PFIL ha_connect::CondFilter(PGLOBAL g, Item *cond) if (!i && (ismul)) return NULL; - if ((res= pval->val_str(&tmp)) == NULL) - return NULL; // To be clarified - switch (args[i]->real_type()) { case COND::STRING_ITEM: pp->Value= PlugSubAllocStr(g, NULL, res->ptr(), res->length()); @@ -2520,7 +2517,11 @@ PFIL ha_connect::CondFilter(PGLOBAL g, Item *cond) return NULL; } // endswitch type - if (trace) + // This was moved because cannot be done for FUNC_ITEM + if ((res= pval->val_str(&tmp)) == NULL) + return NULL; // To be clarified + + if (trace) htrc("Value=%.*s\n", res->length(), res->ptr()); // Append the value to the argument list From 019c9e0a652d0a7abe915c3349c756cce7add459 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Wed, 16 Sep 2015 12:11:28 +0200 Subject: [PATCH 05/67] Fix assert error for where clause with UDF's was fixed in HA_CONNECT::CondFilter moving res= pval->val_str(&tmp) but this was wrong. Now res is only used for strings. modified: storage/connect/ha_connect.cc --- storage/connect/ha_connect.cc | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index c502493357e..8a47e5aef68 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -2486,9 +2486,10 @@ PFIL ha_connect::CondFilter(PGLOBAL g, Item *cond) if (!i && (ismul)) return NULL; - switch (args[i]->real_type()) { + switch (args[i]->real_type()) { case COND::STRING_ITEM: - pp->Value= PlugSubAllocStr(g, NULL, res->ptr(), res->length()); + res= pval->val_str(&tmp); + pp->Value= PlugSubAllocStr(g, NULL, res->ptr(), res->length()); pp->Type= (pp->Value) ? TYPE_STRING : TYPE_ERROR; break; case COND::INT_ITEM: @@ -2517,12 +2518,8 @@ PFIL ha_connect::CondFilter(PGLOBAL g, Item *cond) return NULL; } // endswitch type - // This was moved because cannot be done for FUNC_ITEM - if ((res= pval->val_str(&tmp)) == NULL) - return NULL; // To be clarified - if (trace) - htrc("Value=%.*s\n", res->length(), res->ptr()); + htrc("Value type=%hd\n", pp->Type); // Append the value to the argument list if (pprec) From 151f967380c44d46a6d9a5fda1d19985ebf0e22c Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Sun, 11 Oct 2015 17:06:03 -0400 Subject: [PATCH 06/67] MDEV-7640: CHANGE MASTER TO doesn't work with prepared statements When CHANGE MASTER was executed as a PS, its attributes were wrongly getting reset toward the end of PREPARE. As a result, the subsequent executions had no effect. Fixed by making sure that the CHANGE MASTER attributes are preserved during the lifetime of the PS. --- mysql-test/r/ps_change_master.result | 22 ++++++++++++++ mysql-test/t/ps_change_master.test | 45 ++++++++++++++++++++++++++++ sql/sql_lex.cc | 23 ++++++++++++++ sql/sql_lex.h | 2 ++ sql/sql_prepare.cc | 7 ++++- 5 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 mysql-test/r/ps_change_master.result create mode 100644 mysql-test/t/ps_change_master.test diff --git a/mysql-test/r/ps_change_master.result b/mysql-test/r/ps_change_master.result new file mode 100644 index 00000000000..25069a537a5 --- /dev/null +++ b/mysql-test/r/ps_change_master.result @@ -0,0 +1,22 @@ +# +# CHANGE MASTER TO doesn't work with prepared statements +# +CHANGE MASTER TO MASTER_HOST='host1', MASTER_USER='user1'; +# Master_Host : host1 +# Master_User : user1 +SET @s := "CHANGE MASTER TO MASTER_HOST='host2'"; +PREPARE stmt FROM @s; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; +# Master_Host : host2 +# Master_User : user1 +SET @s := "CHANGE MASTER TO MASTER_USER='user2'"; +PREPARE stmt FROM @s; +EXECUTE stmt; +EXECUTE stmt; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; +# Master_Host : host2 +# Master_User : user2 +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root'; +# End of test diff --git a/mysql-test/t/ps_change_master.test b/mysql-test/t/ps_change_master.test new file mode 100644 index 00000000000..d756b8cd4fb --- /dev/null +++ b/mysql-test/t/ps_change_master.test @@ -0,0 +1,45 @@ +--source include/not_embedded.inc +--source include/have_log_bin.inc + +--echo # +--echo # CHANGE MASTER TO doesn't work with prepared statements +--echo # + +CHANGE MASTER TO MASTER_HOST='host1', MASTER_USER='user1'; + +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +let $master_user= query_get_value(SHOW SLAVE STATUS, Master_User, 1); + +--echo # Master_Host : $master_host +--echo # Master_User : $master_user + +SET @s := "CHANGE MASTER TO MASTER_HOST='host2'"; +PREPARE stmt FROM @s; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +let $master_user= query_get_value(SHOW SLAVE STATUS, Master_User, 1); + +--echo # Master_Host : $master_host +--echo # Master_User : $master_user + +SET @s := "CHANGE MASTER TO MASTER_USER='user2'"; +PREPARE stmt FROM @s; +EXECUTE stmt; +# Multiple executions should not hurt. +EXECUTE stmt; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +let $master_user= query_get_value(SHOW SLAVE STATUS, Master_User, 1); + +--echo # Master_Host : $master_host +--echo # Master_User : $master_user + + +# Reset +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root'; + +--echo # End of test diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 3f3bc40ad59..9d71b1f1226 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -568,6 +568,16 @@ void lex_end(LEX *lex) DBUG_ENTER("lex_end"); DBUG_PRINT("enter", ("lex: 0x%lx", (long) lex)); + lex_end_stage1(lex); + lex_end_stage2(lex); + + DBUG_VOID_RETURN; +} + +void lex_end_stage1(LEX *lex) +{ + DBUG_ENTER("lex_end_stage1"); + /* release used plugins */ if (lex->plugins.elements) /* No function call and no mutex if no plugins. */ { @@ -579,6 +589,19 @@ void lex_end(LEX *lex) delete lex->sphead; lex->sphead= NULL; + DBUG_VOID_RETURN; +} + +/* + MASTER INFO parameters (or state) is normally cleared towards the end + of a statement. But in case of PS, the state needs to be preserved during + its lifetime and should only be cleared on PS close or deallocation. +*/ +void lex_end_stage2(LEX *lex) +{ + DBUG_ENTER("lex_end_stage2"); + + /* Reset LEX_MASTER_INFO */ lex->mi.reset(); DBUG_VOID_RETURN; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 3d008723f66..413afdb4369 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -2947,6 +2947,8 @@ extern void lex_init(void); extern void lex_free(void); extern void lex_start(THD *thd); extern void lex_end(LEX *lex); +extern void lex_end_stage1(LEX *lex); +extern void lex_end_stage2(LEX *lex); void end_lex_with_single_table(THD *thd, TABLE *table, LEX *old_lex); int init_lex_with_single_table(THD *thd, TABLE *table, LEX *lex); extern int MYSQLlex(union YYSTYPE *yylval, THD *thd); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 48d7415a7b3..1790b972724 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -3456,7 +3456,8 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) thd->mdl_context.release_transactional_locks(); } - lex_end(lex); + /* Preserve CHANGE MASTER attributes */ + lex_end_stage1(lex); cleanup_stmt(); thd->restore_backup_statement(this, &stmt_backup); thd->stmt_arena= old_stmt_arena; @@ -4056,6 +4057,10 @@ void Prepared_statement::deallocate() { /* We account deallocate in the same manner as mysqld_stmt_close */ status_var_increment(thd->status_var.com_stmt_close); + + /* It should now be safe to reset CHANGE MASTER parameters */ + lex_end_stage2(lex); + /* Statement map calls delete stmt on erase */ thd->stmt_map.erase(this); } From 978c2a37c01a3adece280d7e9d560fcd67a48cb4 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Sun, 11 Oct 2015 17:06:03 -0400 Subject: [PATCH 07/67] MDEV-7640: CHANGE MASTER TO doesn't work with prepared statements When CHANGE MASTER was executed as a PS, its attributes were wrongly getting reset toward the end of PREPARE. As a result, the subsequent executions had no effect. Fixed by making sure that the CHANGE MASTER attributes are preserved during the lifetime of the PS. --- mysql-test/r/ps_change_master.result | 22 ++++++++++++++ mysql-test/t/ps_change_master.test | 45 ++++++++++++++++++++++++++++ sql/sql_lex.cc | 23 ++++++++++++++ sql/sql_lex.h | 2 ++ sql/sql_prepare.cc | 7 ++++- 5 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 mysql-test/r/ps_change_master.result create mode 100644 mysql-test/t/ps_change_master.test diff --git a/mysql-test/r/ps_change_master.result b/mysql-test/r/ps_change_master.result new file mode 100644 index 00000000000..25069a537a5 --- /dev/null +++ b/mysql-test/r/ps_change_master.result @@ -0,0 +1,22 @@ +# +# CHANGE MASTER TO doesn't work with prepared statements +# +CHANGE MASTER TO MASTER_HOST='host1', MASTER_USER='user1'; +# Master_Host : host1 +# Master_User : user1 +SET @s := "CHANGE MASTER TO MASTER_HOST='host2'"; +PREPARE stmt FROM @s; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; +# Master_Host : host2 +# Master_User : user1 +SET @s := "CHANGE MASTER TO MASTER_USER='user2'"; +PREPARE stmt FROM @s; +EXECUTE stmt; +EXECUTE stmt; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; +# Master_Host : host2 +# Master_User : user2 +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root'; +# End of test diff --git a/mysql-test/t/ps_change_master.test b/mysql-test/t/ps_change_master.test new file mode 100644 index 00000000000..d756b8cd4fb --- /dev/null +++ b/mysql-test/t/ps_change_master.test @@ -0,0 +1,45 @@ +--source include/not_embedded.inc +--source include/have_log_bin.inc + +--echo # +--echo # CHANGE MASTER TO doesn't work with prepared statements +--echo # + +CHANGE MASTER TO MASTER_HOST='host1', MASTER_USER='user1'; + +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +let $master_user= query_get_value(SHOW SLAVE STATUS, Master_User, 1); + +--echo # Master_Host : $master_host +--echo # Master_User : $master_user + +SET @s := "CHANGE MASTER TO MASTER_HOST='host2'"; +PREPARE stmt FROM @s; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +let $master_user= query_get_value(SHOW SLAVE STATUS, Master_User, 1); + +--echo # Master_Host : $master_host +--echo # Master_User : $master_user + +SET @s := "CHANGE MASTER TO MASTER_USER='user2'"; +PREPARE stmt FROM @s; +EXECUTE stmt; +# Multiple executions should not hurt. +EXECUTE stmt; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +let $master_user= query_get_value(SHOW SLAVE STATUS, Master_User, 1); + +--echo # Master_Host : $master_host +--echo # Master_User : $master_user + + +# Reset +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root'; + +--echo # End of test diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 9ccafa75ca7..957764c56bb 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -545,6 +545,16 @@ void lex_end(LEX *lex) DBUG_ENTER("lex_end"); DBUG_PRINT("enter", ("lex: 0x%lx", (long) lex)); + lex_end_stage1(lex); + lex_end_stage2(lex); + + DBUG_VOID_RETURN; +} + +void lex_end_stage1(LEX *lex) +{ + DBUG_ENTER("lex_end_stage1"); + /* release used plugins */ if (lex->plugins.elements) /* No function call and no mutex if no plugins. */ { @@ -556,6 +566,19 @@ void lex_end(LEX *lex) delete lex->sphead; lex->sphead= NULL; + DBUG_VOID_RETURN; +} + +/* + MASTER INFO parameters (or state) is normally cleared towards the end + of a statement. But in case of PS, the state needs to be preserved during + its lifetime and should only be cleared on PS close or deallocation. +*/ +void lex_end_stage2(LEX *lex) +{ + DBUG_ENTER("lex_end_stage2"); + + /* Reset LEX_MASTER_INFO */ lex->mi.reset(); DBUG_VOID_RETURN; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index aa59d76245b..6454da24af3 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -2940,6 +2940,8 @@ extern void lex_init(void); extern void lex_free(void); extern void lex_start(THD *thd); extern void lex_end(LEX *lex); +extern void lex_end_stage1(LEX *lex); +extern void lex_end_stage2(LEX *lex); void end_lex_with_single_table(THD *thd, TABLE *table, LEX *old_lex); int init_lex_with_single_table(THD *thd, TABLE *table, LEX *lex); extern int MYSQLlex(union YYSTYPE *yylval, THD *thd); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index e948813584d..4fcc007d104 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -3416,7 +3416,8 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) thd->mdl_context.release_transactional_locks(); } - lex_end(lex); + /* Preserve CHANGE MASTER attributes */ + lex_end_stage1(lex); cleanup_stmt(); thd->restore_backup_statement(this, &stmt_backup); thd->stmt_arena= old_stmt_arena; @@ -3997,6 +3998,10 @@ void Prepared_statement::deallocate() { /* We account deallocate in the same manner as mysqld_stmt_close */ status_var_increment(thd->status_var.com_stmt_close); + + /* It should now be safe to reset CHANGE MASTER parameters */ + lex_end_stage2(lex); + /* Statement map calls delete stmt on erase */ thd->stmt_map.erase(this); } From 90209463d0a4016d9f86f8e31dabdd61dbe48763 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sun, 18 Oct 2015 15:03:45 +0200 Subject: [PATCH 08/67] Fix MDEV-8926 modified: storage/connect/ha_connect.cc --- storage/connect/ha_connect.cc | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 8a47e5aef68..0b5ddefb51e 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -169,7 +169,7 @@ #define JSONMAX 10 // JSON Default max grp size extern "C" { - char version[]= "Version 1.03.0007 July 05, 2015"; + char version[]= "Version 1.03.0007 October 18, 2015"; #if defined(__WIN__) char compver[]= "Version 1.03.0007 " __DATE__ " " __TIME__; char slash= '\\'; @@ -2471,7 +2471,18 @@ PFIL ha_connect::CondFilter(PGLOBAL g, Item *cond) !(colp[i]= tdbp->ColDB(g, (PSZ)pField->field->field_name, 0))) return NULL; // Column does not belong to this table - if (trace) { + // These types are not yet implemented (buggy) + switch (pField->field->type()) { + case MYSQL_TYPE_TIMESTAMP: + case MYSQL_TYPE_DATE: + case MYSQL_TYPE_TIME: + case MYSQL_TYPE_DATETIME: + case MYSQL_TYPE_YEAR: + case MYSQL_TYPE_NEWDATE: + return NULL; + } // endswitch type + + if (trace) { htrc("Field index=%d\n", pField->field->field_index); htrc("Field name=%s\n", pField->field->field_name); } // endif trace From 9a3ff0789fbf6c0ea627415c90ae5487449f433b Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Mon, 19 Oct 2015 12:15:49 +0200 Subject: [PATCH 09/67] MDEV-8565: COLUMN_CHECK fails on valid data Check allows zero lengts int/uint now. --- mysql-test/r/dyncol.result | 15 +++++++++++++++ mysql-test/t/dyncol.test | 12 ++++++++++++ mysys/ma_dyncol.c | 6 ++++-- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/dyncol.result b/mysql-test/r/dyncol.result index 04ab385bca6..62e3b1c7331 100644 --- a/mysql-test/r/dyncol.result +++ b/mysql-test/r/dyncol.result @@ -1805,5 +1805,20 @@ set impressions = column_add(impressions, ); drop table t1; # +# MDEV-8565: COLUMN_CHECK fails on valid data +# +SELECT COLUMN_CHECK(COLUMN_CREATE('a',0,'b','1')); +COLUMN_CHECK(COLUMN_CREATE('a',0,'b','1')) +1 +SELECT COLUMN_CHECK(COLUMN_CREATE('a',1,'b','1')); +COLUMN_CHECK(COLUMN_CREATE('a',1,'b','1')) +1 +SELECT COLUMN_JSON(COLUMN_CREATE('a',0,'b','1')); +COLUMN_JSON(COLUMN_CREATE('a',0,'b','1')) +{"a":0,"b":"1"} +SELECT COLUMN_JSON(COLUMN_CREATE('a',1,'b','1')); +COLUMN_JSON(COLUMN_CREATE('a',1,'b','1')) +{"a":1,"b":"1"} +# # end of 10.0 tests # diff --git a/mysql-test/t/dyncol.test b/mysql-test/t/dyncol.test index 86dcee8148a..ac55fec3e2b 100644 --- a/mysql-test/t/dyncol.test +++ b/mysql-test/t/dyncol.test @@ -871,6 +871,18 @@ set impressions = column_add(impressions, drop table t1; +--echo # +--echo # MDEV-8565: COLUMN_CHECK fails on valid data +--echo # + +SELECT COLUMN_CHECK(COLUMN_CREATE('a',0,'b','1')); + +SELECT COLUMN_CHECK(COLUMN_CREATE('a',1,'b','1')); + +SELECT COLUMN_JSON(COLUMN_CREATE('a',0,'b','1')); + +SELECT COLUMN_JSON(COLUMN_CREATE('a',1,'b','1')); + --echo # --echo # end of 10.0 tests --echo # diff --git a/mysys/ma_dyncol.c b/mysys/ma_dyncol.c index a7a048acac1..7e47856ce2d 100644 --- a/mysys/ma_dyncol.c +++ b/mysys/ma_dyncol.c @@ -3723,10 +3723,12 @@ mariadb_dyncol_check(DYNAMIC_COLUMN *str) if (prev_type != DYN_COL_NULL) { /* It is not first entry */ - if (prev_data_offset >= data_offset) + if (prev_data_offset > data_offset || + ((prev_type != DYN_COL_INT && + prev_type != DYN_COL_UINT) && prev_data_offset == data_offset)) { DBUG_PRINT("info", ("Field order: %u Previous data offset: %u" - " >= Current data offset: %u", + " >(=) Current data offset: %u", (uint)i, (uint)prev_data_offset, (uint)data_offset)); From d51e466e63bce9c8ef805ee7271262a77abe7f85 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Tue, 20 Oct 2015 13:20:10 +0200 Subject: [PATCH 10/67] Fix MDEV-8966 modified: storage/connect/ha_connect.cc --- storage/connect/ha_connect.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 0b5ddefb51e..e6510c3c82a 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -169,7 +169,7 @@ #define JSONMAX 10 // JSON Default max grp size extern "C" { - char version[]= "Version 1.03.0007 October 18, 2015"; + char version[]= "Version 1.03.0007 October 20, 2015"; #if defined(__WIN__) char compver[]= "Version 1.03.0007 " __DATE__ " " __TIME__; char slash= '\\'; @@ -1134,7 +1134,10 @@ PTOS ha_connect::GetTableOptionStruct(TABLE_SHARE *s) { TABLE_SHARE *tsp= (tshp) ? tshp : (s) ? s : table_share; - return (tsp) ? tsp->option_struct : NULL; + return (tsp && (!tsp->db_plugin || + !stricmp(plugin_name(tsp->db_plugin)->str, "connect") || + !stricmp(plugin_name(tsp->db_plugin)->str, "partition"))) + ? tsp->option_struct : NULL; } // end of GetTableOptionStruct /****************************************************************************/ From df804208657dfae10e24d656d9228f05e57b14a5 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 21 Oct 2015 14:42:56 +0200 Subject: [PATCH 11/67] fix events_1 test for October 2015 cherry-picked 7454f1c5 from 10.1 --- mysql-test/r/events_1.result | 3 ++- mysql-test/t/events_1.test | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/events_1.result b/mysql-test/r/events_1.result index 5a64cf14ef5..475a190d73d 100644 --- a/mysql-test/r/events_1.result +++ b/mysql-test/r/events_1.result @@ -114,7 +114,8 @@ create table t_event3 (a int, b float); drop event if exists event3; Warnings: Note 1305 Event event3 does not exist -create event event3 on schedule every 50 + 10 minute starts date_add("20100101", interval 5 minute) ends date_add("20151010", interval 5 day) comment "portokala_comment" DO insert into t_event3 values (unix_timestamp(), rand()); +create event event3 on schedule every 50 + 10 minute starts date_add("20100101", interval 5 minute) ends date_add("20251010", interval 5 day) +comment "portokala_comment" DO insert into t_event3 values (unix_timestamp(), rand()); select count(*) from t_event3; count(*) 0 diff --git a/mysql-test/t/events_1.test b/mysql-test/t/events_1.test index 7f31e3fc881..7b0012c7079 100644 --- a/mysql-test/t/events_1.test +++ b/mysql-test/t/events_1.test @@ -125,7 +125,8 @@ drop event existant; create table t_event3 (a int, b float); drop event if exists event3; -create event event3 on schedule every 50 + 10 minute starts date_add("20100101", interval 5 minute) ends date_add("20151010", interval 5 day) comment "portokala_comment" DO insert into t_event3 values (unix_timestamp(), rand()); +create event event3 on schedule every 50 + 10 minute starts date_add("20100101", interval 5 minute) ends date_add("20251010", interval 5 day) + comment "portokala_comment" DO insert into t_event3 values (unix_timestamp(), rand()); let $wait_condition=SELECT count(*)=0 from t_event3; --source include/wait_condition.inc select count(*) from t_event3; From 95faf34d859aee242812fae31629b224feeb868a Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Mon, 12 Oct 2015 13:05:31 +0300 Subject: [PATCH 12/67] Set opt_noacl (running with--skip-grant-tables) to 0 if we reload grant tables. --- sql/sql_reload.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc index 7390aa0bb0f..4707aed933e 100644 --- a/sql/sql_reload.cc +++ b/sql/sql_reload.cc @@ -93,6 +93,7 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options, my_error(ER_UNKNOWN_ERROR, MYF(0)); } } + opt_noacl= 0; if (tmp_thd) { From 18f7dfed179204dcfc02a27790e22bb9cc4e2e32 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Thu, 15 Oct 2015 12:11:17 +0300 Subject: [PATCH 13/67] Allow mysql_upgrade to enable event after table is corrected new features: set event_scheduler=ON|OFF will now try to init event scheduler if it's not enabled set event_scheduler=default will try to enable it based on the value of the event_scheduler when mysqld was started --- client/mysql_upgrade.c | 1 + mysql-test/r/events_restart.result | 24 +++- mysql-test/r/mysql_upgrade-6984.result | 1 + mysql-test/r/skip_grants.result | 4 +- mysql-test/t/events_restart.test | 14 +- mysql-test/t/mysql_upgrade-6984.test | 3 +- mysql-test/t/skip_grants.test | 2 +- scripts/mysql_system_tables_fix.sql | 2 + sql/events.cc | 178 ++++++++++++++----------- sql/events.h | 16 ++- sql/mysqld.cc | 10 +- sql/sql_error.cc | 2 + sql/sys_vars.cc | 40 ++++-- 13 files changed, 188 insertions(+), 109 deletions(-) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index db120896bda..a6ba0bc2ed7 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -865,6 +865,7 @@ static const char *expected_errors[]= "ERROR 1060", /* Duplicate column name */ "ERROR 1061", /* Duplicate key name */ "ERROR 1054", /* Unknown column */ + "ERROR 1290", /* RR_OPTION_PREVENTS_STATEMENT */ 0 }; diff --git a/mysql-test/r/events_restart.result b/mysql-test/r/events_restart.result index ba3aa503b63..0caac907f64 100644 --- a/mysql-test/r/events_restart.result +++ b/mysql-test/r/events_restart.result @@ -18,7 +18,7 @@ change column body body longtext character set utf8 collate utf8_bin; use events_test; select @@event_scheduler; @@event_scheduler -DISABLED +OFF show events; ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start select event_name from information_schema.events; @@ -40,12 +40,12 @@ ERROR HY000: Cannot proceed because system tables used by Event Scheduler were f drop event intact_check; ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start set global event_scheduler=on; -ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start +ERROR HY000: Event Scheduler: An error occurred when initializing system tables. Disabling the Event Scheduler. set global event_scheduler=off; -ERROR HY000: Cannot proceed because system tables used by Event Scheduler were found damaged at server start +ERROR HY000: Event Scheduler: An error occurred when initializing system tables. Disabling the Event Scheduler. show variables like 'event_scheduler'; Variable_name Value -event_scheduler DISABLED +event_scheduler OFF Make sure that we still can create and drop databases, and no warnings are produced. drop database if exists mysqltest_database_not_exists; @@ -58,6 +58,22 @@ Error 1545 Failed to open mysql.event Restore the original mysql.event table drop table mysql.event; rename table event_like to mysql.event; +check that we can now enable events without restart +set global event_scheduler=original; +Warnings: +Note 1408 Event Scheduler: Loaded 3 events +select @@global.event_scheduler; +@@global.event_scheduler +ON +set global event_scheduler=on; +select @@global.event_scheduler; +@@global.event_scheduler +ON +show events; +Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation +events_test abc1 root@localhost SYSTEM RECURRING # 1 SECOND # # ENABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci +events_test abc2 root@localhost SYSTEM RECURRING # 1 SECOND # # ENABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci +events_test abc3 root@localhost SYSTEM RECURRING # 1 SECOND # # ENABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci Now let's restart the server again use events_test; select @@event_scheduler; diff --git a/mysql-test/r/mysql_upgrade-6984.result b/mysql-test/r/mysql_upgrade-6984.result index 7890b66d494..6aea4806ddb 100644 --- a/mysql-test/r/mysql_upgrade-6984.result +++ b/mysql-test/r/mysql_upgrade-6984.result @@ -57,3 +57,4 @@ Phase 6/6: Running 'FLUSH PRIVILEGES' OK update mysql.user set password='' where user='root'; flush privileges; +set global event_scheduler=OFF; diff --git a/mysql-test/r/skip_grants.result b/mysql-test/r/skip_grants.result index b178e0ecfa7..75792a15afa 100644 --- a/mysql-test/r/skip_grants.result +++ b/mysql-test/r/skip_grants.result @@ -59,7 +59,9 @@ DROP FUNCTION f1; DROP FUNCTION f2; DROP FUNCTION f3; set global event_scheduler=1; -ERROR HY000: The MariaDB server is running with the --event-scheduler=DISABLED or --skip-grant-tables option so it cannot execute this statement +Warnings: +Note 1408 Event Scheduler: Loaded 0 events +set global event_scheduler=0; select count(*) from information_schema.COLUMN_PRIVILEGES; count(*) 0 diff --git a/mysql-test/t/events_restart.test b/mysql-test/t/events_restart.test index c6152e5d961..7f01859e059 100644 --- a/mysql-test/t/events_restart.test +++ b/mysql-test/t/events_restart.test @@ -71,9 +71,9 @@ drop event intact_check_1; drop event intact_check_2; --error ER_EVENTS_DB_ERROR drop event intact_check; ---error ER_EVENTS_DB_ERROR +--error ER_STARTUP set global event_scheduler=on; ---error ER_EVENTS_DB_ERROR +--error ER_STARTUP set global event_scheduler=off; show variables like 'event_scheduler'; --echo Make sure that we still can create and drop databases, @@ -84,6 +84,16 @@ drop database mysqltest_db1; --echo Restore the original mysql.event table drop table mysql.event; rename table event_like to mysql.event; + +--echo check that we can now enable events without restart +set global event_scheduler=original; +select @@global.event_scheduler; +set global event_scheduler=on; +select @@global.event_scheduler; +--sorted_result +--replace_column 6 # 9 # 10 # +show events; + --echo Now let's restart the server again --source include/restart_mysqld.inc diff --git a/mysql-test/t/mysql_upgrade-6984.test b/mysql-test/t/mysql_upgrade-6984.test index 6f10d3f33e9..9bbfbeb3f87 100644 --- a/mysql-test/t/mysql_upgrade-6984.test +++ b/mysql-test/t/mysql_upgrade-6984.test @@ -19,4 +19,5 @@ connect(con1,localhost,root,foo,,,); update mysql.user set password='' where user='root'; flush privileges; - +# Load event table +set global event_scheduler=OFF; diff --git a/mysql-test/t/skip_grants.test b/mysql-test/t/skip_grants.test index 6f4d23e1e14..77339478fdb 100644 --- a/mysql-test/t/skip_grants.test +++ b/mysql-test/t/skip_grants.test @@ -112,8 +112,8 @@ DROP FUNCTION f3; # # Bug #26807 "set global event_scheduler=1" and --skip-grant-tables crashes server # ---error ER_OPTION_PREVENTS_STATEMENT set global event_scheduler=1; +set global event_scheduler=0; # # Bug#26285 Selecting information_schema crahes server diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql index b81eb4e8e40..33b4306b103 100644 --- a/scripts/mysql_system_tables_fix.sql +++ b/scripts/mysql_system_tables_fix.sql @@ -597,6 +597,8 @@ ALTER TABLE event ADD body_utf8 longblob DEFAULT NULL AFTER db_collation; ALTER TABLE event MODIFY body_utf8 longblob DEFAULT NULL; +# Enable event scheduler if the event table was not up to date before. +set global event_scheduler=original; # # TRIGGER privilege diff --git a/sql/events.cc b/sql/events.cc index cf4c4a8fe75..32d194e3bac 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -80,7 +80,8 @@ Event_queue *Events::event_queue; Event_scheduler *Events::scheduler; Event_db_repository *Events::db_repository; ulong Events::opt_event_scheduler= Events::EVENTS_OFF; -bool Events::check_system_tables_error= FALSE; +ulong Events::startup_state= Events::EVENTS_OFF; +ulong Events::inited; /* @@ -114,7 +115,7 @@ bool Events::check_if_system_tables_error() { DBUG_ENTER("Events::check_if_system_tables_error"); - if (check_system_tables_error) + if (!inited) { my_error(ER_EVENTS_DB_ERROR, MYF(0)); DBUG_RETURN(TRUE); @@ -257,10 +258,10 @@ common_1_lev_code: /** - Create a new query string for removing executable comments - for avoiding leak and keeping consistency of the execution + Create a new query string for removing executable comments + for avoiding leak and keeping consistency of the execution on master and slave. - + @param[in] thd Thread handler @param[in] buf Query string @@ -281,7 +282,7 @@ create_query_string(THD *thd, String *buf) thd->lex->stmt_definition_end - thd->lex->stmt_definition_begin)) return 1; - + return 0; } @@ -336,8 +337,8 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, if (parse_data->do_not_create) DBUG_RETURN(FALSE); - /* - Turn off row binlogging of this statement and use statement-based + /* + Turn off row binlogging of this statement and use statement-based so that all supporting tables are updated for CREATE EVENT command. */ save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); @@ -384,8 +385,10 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, String log_query; if (create_query_string(thd, &log_query)) { - sql_print_error("Event Error: An error occurred while creating query " - "string, before writing it into binary log."); + my_message_sql(ER_STARTUP, + "Event Error: An error occurred while creating query " + "string, before writing it into binary log.", + MYF(ME_NOREFRESH)); ret= true; } else @@ -473,8 +476,8 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, } } - /* - Turn off row binlogging of this statement and use statement-based + /* + Turn off row binlogging of this statement and use statement-based so that all supporting tables are updated for UPDATE EVENT command. */ save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); @@ -752,6 +755,13 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */) int ret; DBUG_ENTER("Events::fill_schema_events"); + /* + If we didn't start events because of --skip-grant-tables, return an + empty set + */ + if (opt_noacl) + DBUG_RETURN(0); + if (check_if_system_tables_error()) DBUG_RETURN(1); @@ -780,6 +790,7 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */) /** Initializes the scheduler's structures. + @param THD or null (if called by init) @param opt_noacl_or_bootstrap TRUE if there is --skip-grant-tables or --bootstrap option. In that case we disable the event scheduler. @@ -787,44 +798,56 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */) @note This function is not synchronized. @retval FALSE Perhaps there was an error, and the event scheduler - is disabled. But the error is not fatal and the + is disabled. But the error is not fatal and the server start up can continue. @retval TRUE Fatal error. Startup must terminate (call unireg_abort()). */ bool -Events::init(bool opt_noacl_or_bootstrap) +Events::init(THD *thd, bool opt_noacl_or_bootstrap) { - - THD *thd; int err_no; bool res= FALSE; - + bool had_thd= thd != 0; DBUG_ENTER("Events::init"); + DBUG_ASSERT(inited == 0); + + /* + Was disabled explicitly from the command line + */ + if (opt_event_scheduler == Events::EVENTS_DISABLED || + opt_noacl_or_bootstrap) + DBUG_RETURN(FALSE); + /* We need a temporary THD during boot */ - if (!(thd= new THD())) + if (!thd) { - res= TRUE; - goto end; + + if (!(thd= new THD())) + { + res= TRUE; + goto end; + } + /* + The thread stack does not start from this function but we cannot + guess the real value. So better some value that doesn't assert than + no value. + */ + thd->thread_stack= (char*) &thd; + thd->store_globals(); + /* + Set current time for the thread that handles events. + Current time is stored in data member start_time of THD class. + Subsequently, this value is used to check whether event was expired + when make loading events from storage. Check for event expiration time + is done at Event_queue_element::compute_next_execution_time() where + event's status set to Event_parse_data::DISABLED and dropped flag set + to true if event was expired. + */ + thd->set_time(); } - /* - The thread stack does not start from this function but we cannot - guess the real value. So better some value that doesn't assert than - no value. - */ - thd->thread_stack= (char*) &thd; - thd->store_globals(); - /* - Set current time for the thread that handles events. - Current time is stored in data member start_time of THD class. - Subsequently, this value is used to check whether event was expired - when make loading events from storage. Check for event expiration time - is done at Event_queue_element::compute_next_execution_time() where - event's status set to Event_parse_data::DISABLED and dropped flag set - to true if event was expired. - */ - thd->set_time(); + /* We will need Event_db_repository anyway, even if the scheduler is disabled - to perform events DDL. @@ -844,28 +867,19 @@ Events::init(bool opt_noacl_or_bootstrap) are most likely not there and we're going to disable the event scheduler anyway. */ - if (opt_noacl_or_bootstrap || Event_db_repository::check_system_tables(thd)) + if (Event_db_repository::check_system_tables(thd)) { - if (! opt_noacl_or_bootstrap) - { - sql_print_error("Event Scheduler: An error occurred when initializing " - "system tables. Disabling the Event Scheduler."); - check_system_tables_error= TRUE; - } - + delete db_repository; + db_repository= 0; + my_message(ER_STARTUP, + "Event Scheduler: An error occurred when initializing " + "system tables. Disabling the Event Scheduler.", + MYF(ME_NOREFRESH)); /* Disable the scheduler since the system tables are not up to date */ - opt_event_scheduler= EVENTS_DISABLED; + opt_event_scheduler= EVENTS_OFF; goto end; } - /* - Was disabled explicitly from the command line, or because we're running - with --skip-grant-tables, or --bootstrap, or because we have no system - tables. - */ - if (opt_event_scheduler == Events::EVENTS_DISABLED) - goto end; - DBUG_ASSERT(opt_event_scheduler == Events::EVENTS_ON || opt_event_scheduler == Events::EVENTS_OFF); @@ -880,22 +894,23 @@ Events::init(bool opt_noacl_or_bootstrap) if (event_queue->init_queue(thd) || load_events_from_db(thd) || (opt_event_scheduler == EVENTS_ON && scheduler->start(&err_no))) { - sql_print_error("Event Scheduler: Error while loading from disk."); + my_message_sql(ER_STARTUP, + "Event Scheduler: Error while loading from mysql.event table.", + MYF(ME_NOREFRESH)); res= TRUE; /* fatal error: request unireg_abort */ goto end; } Event_worker_thread::init(db_repository); + inited= 1; end: if (res) + deinit(); + if (!had_thd) { - delete db_repository; - delete event_queue; - delete scheduler; + delete thd; + set_current_thd(0); } - delete thd; - /* Remember that we don't have a THD */ - set_current_thd(0); DBUG_RETURN(res); } @@ -915,17 +930,14 @@ Events::deinit() { DBUG_ENTER("Events::deinit"); - if (opt_event_scheduler != EVENTS_DISABLED) - { - delete scheduler; - scheduler= NULL; /* safety */ - delete event_queue; - event_queue= NULL; /* safety */ - } - + delete scheduler; + scheduler= NULL; /* For restart */ + delete event_queue; + event_queue= NULL; /* For restart */ delete db_repository; - db_repository= NULL; /* safety */ + db_repository= NULL; /* For restart */ + inited= 0; DBUG_VOID_RETURN; } @@ -1028,7 +1040,7 @@ Events::dump_internal_status() holding LOCK_global_system_variables. */ mysql_mutex_lock(&LOCK_global_system_variables); - if (opt_event_scheduler == EVENTS_DISABLED) + if (!inited) puts("The Event Scheduler is disabled"); else { @@ -1042,11 +1054,13 @@ Events::dump_internal_status() bool Events::start(int *err_no) { + DBUG_ASSERT(inited); return scheduler->start(err_no); } bool Events::stop() { + DBUG_ASSERT(inited); return scheduler->stop(); } @@ -1076,7 +1090,6 @@ Events::load_events_from_db(THD *thd) bool ret= TRUE; uint count= 0; ulong saved_master_access; - DBUG_ENTER("Events::load_events_from_db"); DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd)); @@ -1101,7 +1114,9 @@ Events::load_events_from_db(THD *thd) if (ret) { - sql_print_error("Event Scheduler: Failed to open table mysql.event"); + my_message_sql(ER_STARTUP, + "Event Scheduler: Failed to open table mysql.event", + MYF(ME_NOREFRESH)); DBUG_RETURN(TRUE); } @@ -1123,9 +1138,11 @@ Events::load_events_from_db(THD *thd) if (et->load_from_row(thd, table)) { - sql_print_error("Event Scheduler: " - "Error while loading events from mysql.event. " - "The table probably contains bad data or is corrupted"); + my_message(ER_STARTUP, + "Event Scheduler: " + "Error while loading events from mysql.event. " + "The table probably contains bad data or is corrupted", + MYF(ME_NOREFRESH)); delete et; goto end; } @@ -1163,9 +1180,12 @@ Events::load_events_from_db(THD *thd) } } } - if (global_system_variables.log_warnings) - sql_print_information("Event Scheduler: Loaded %d event%s", - count, (count == 1) ? "" : "s"); + my_printf_error(ER_STARTUP, + "Event Scheduler: Loaded %d event%s", + MYF(ME_NOREFRESH | + (global_system_variables.log_warnings) ? + ME_JUST_INFO: 0), + count, (count == 1) ? "" : "s"); ret= FALSE; end: diff --git a/sql/events.h b/sql/events.h index 646fd257d52..91a0e6f28eb 100644 --- a/sql/events.h +++ b/sql/events.h @@ -79,9 +79,11 @@ public: and the @@global.event_scheduler SQL variable. See sys_var.cc */ - enum enum_opt_event_scheduler { EVENTS_OFF, EVENTS_ON, EVENTS_DISABLED }; + enum enum_opt_event_scheduler { EVENTS_OFF, EVENTS_ON, EVENTS_DISABLED, + EVENTS_ORIGINAL }; /* Protected using LOCK_global_system_variables only. */ - static ulong opt_event_scheduler; + static ulong opt_event_scheduler, startup_state; + static ulong inited; static bool check_if_system_tables_error(); static bool start(int *err_no); static bool stop(); @@ -91,8 +93,7 @@ public: static Event_db_repository * get_db_repository() { return db_repository; } - static bool - init(bool opt_noacl); + static bool init(THD *thd, bool opt_noacl); static void deinit(); @@ -130,6 +131,11 @@ public: static void dump_internal_status(); + static void set_original_state(ulong startup_state_org) + { + startup_state= startup_state_org; + } + private: static bool @@ -139,8 +145,6 @@ private: static Event_queue *event_queue; static Event_scheduler *scheduler; static Event_db_repository *db_repository; - /* Set to TRUE if an error at start up */ - static bool check_system_tables_error; private: /* Prevent use of these */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 204bf75909f..bc4d857d704 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5507,7 +5507,15 @@ int mysqld_main(int argc, char **argv) execute_ddl_log_recovery(); - if (Events::init(opt_noacl || opt_bootstrap)) + /* + Change EVENTS_ORIGINAL to EVENTS_OFF (the default value) as there is no + point in using ORIGINAL during startup + */ + if (Events::opt_event_scheduler == Events::EVENTS_ORIGINAL) + Events::opt_event_scheduler= Events::EVENTS_OFF; + + Events::set_original_state(Events::opt_event_scheduler); + if (Events::init((THD*) 0, opt_noacl || opt_bootstrap)) unireg_abort(1); if (opt_bootstrap) diff --git a/sql/sql_error.cc b/sql/sql_error.cc index 3e18b701031..b2fa8187925 100644 --- a/sql/sql_error.cc +++ b/sql/sql_error.cc @@ -510,8 +510,10 @@ Diagnostics_area::set_error_status(uint sql_errno, void Diagnostics_area::disable_status() { + DBUG_ENTER("disable_status"); DBUG_ASSERT(! is_set()); m_status= DA_DISABLED; + DBUG_VOID_RETURN; } Warning_info::Warning_info(ulonglong warn_id_arg, diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index d0ee489aa82..12aaf0a7e7d 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -815,30 +815,26 @@ static Sys_var_ulong Sys_delayed_queue_size( VALID_RANGE(1, UINT_MAX), DEFAULT(DELAYED_QUEUE_SIZE), BLOCK_SIZE(1)); #ifdef HAVE_EVENT_SCHEDULER -static const char *event_scheduler_names[]= { "OFF", "ON", "DISABLED", NullS }; +static const char *event_scheduler_names[]= { "OFF", "ON", "DISABLED", + "ORIGINAL", NullS }; static bool event_scheduler_check(sys_var *self, THD *thd, set_var *var) { - /* DISABLED is only accepted on the command line */ - if (var->save_result.ulonglong_value == Events::EVENTS_DISABLED) - return true; - /* - If the scheduler was disabled because there are no/bad - system tables, produce a more meaningful error message - than ER_OPTION_PREVENTS_STATEMENT - */ - if (Events::check_if_system_tables_error()) - return true; if (Events::opt_event_scheduler == Events::EVENTS_DISABLED) { my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--event-scheduler=DISABLED or --skip-grant-tables"); return true; } + /* DISABLED is only accepted on the command line */ + if (var->save_result.ulonglong_value == Events::EVENTS_DISABLED) + return true; return false; } + static bool event_scheduler_update(sys_var *self, THD *thd, enum_var_type type) { int err_no= 0; + bool ret; uint opt_event_scheduler_value= Events::opt_event_scheduler; mysql_mutex_unlock(&LOCK_global_system_variables); /* @@ -857,9 +853,25 @@ static bool event_scheduler_update(sys_var *self, THD *thd, enum_var_type type) rare and it's difficult to avoid it without opening up possibilities for deadlocks. See bug#51160. */ - bool ret= opt_event_scheduler_value == Events::EVENTS_ON - ? Events::start(&err_no) - : Events::stop(); + + /* EVENTS_ORIGINAL means we should revert back to the startup state */ + if (opt_event_scheduler_value == Events::EVENTS_ORIGINAL) + { + opt_event_scheduler_value= Events::opt_event_scheduler= + Events::startup_state; + } + + /* + If the scheduler was not properly inited (because of wrong system tables), + try to init it again. This is needed for mysql_upgrade to work properly if + the event tables where upgraded. + */ + if (!Events::inited && (Events::init(thd, 0) || !Events::inited)) + ret= 1; + else + ret= opt_event_scheduler_value == Events::EVENTS_ON ? + Events::start(&err_no) : + Events::stop(); mysql_mutex_lock(&LOCK_global_system_variables); if (ret) { From b35f9972c886a7b1481270b6b0b3974f6009197d Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Wed, 21 Oct 2015 19:24:01 +0200 Subject: [PATCH 14/67] Fix MDEV-8882 modified: storage/connect/tabodbc.cpp --- storage/connect/tabodbc.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp index 098ed1ac114..31854870ed2 100644 --- a/storage/connect/tabodbc.cpp +++ b/storage/connect/tabodbc.cpp @@ -321,10 +321,21 @@ PSZ TDBODBC::GetFile(PGLOBAL g) { if (Connect) { char *p1, *p2; - size_t n; + int i; + size_t n; - if ((p1 = strstr(Connect, "DBQ="))) { - p1 += 4; // Beginning of file name + if (!(p1 = strstr(Connect, "DBQ="))) { + char *p, *lc = strlwr(PlugDup(g, Connect)); + + if ((p = strstr(lc, "database="))) + p1 = Connect + (p - lc); + + i = 9; + } else + i = 4; + + if (p1) { + p1 += i; // Beginning of file name p2 = strchr(p1, ';'); // End of file path/name // Make the File path/name from the connect string From e5cce2b99f012785b86648af9ab5d7052a3db3cc Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 22 Oct 2015 07:15:23 +0200 Subject: [PATCH 15/67] fix build on sol10-64 --- BUILD/compile-solaris-amd64 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD/compile-solaris-amd64 b/BUILD/compile-solaris-amd64 index 2ae8ff333e8..8b032309beb 100755 --- a/BUILD/compile-solaris-amd64 +++ b/BUILD/compile-solaris-amd64 @@ -3,6 +3,6 @@ export LDFLAGS='-m64 -lmtmalloc -R/usr/sfw/lib/64' export CFLAGS='-mtune=i386 -D__sun -m64 -mtune=athlon64' export CXXFLAGS='-mtune=i386 -D__sun -m64 -mtune=athlon64' -cmake . -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DWITH_EXTRA_CHARSETS=complex -DWITH_READLINE=ON -DWITH_SSL=bundled -DWITH_MAX=ON -DWITH_EMBEDDED_SERVER=ON +cmake . -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DWITH_EXTRA_CHARSETS=complex -DWITH_READLINE=ON -DWITH_SSL=bundled -DWITH_MAX=ON -DWITH_EMBEDDED_SERVER=ON -DWITH_ZLIB=bundled gmake -j6 VERBOSE=1 From e257b8b9598ff861a97bbc2c43e2d7e88a997523 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 21 Oct 2015 16:22:20 +0200 Subject: [PATCH 16/67] fix the dbug tag name --- sql/sql_parse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a665f0314e8..21d006537ac 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -670,7 +670,7 @@ static char *fgets_fn(char *buffer, size_t size, fgets_input_t input, int *error static void handle_bootstrap_impl(THD *thd) { MYSQL_FILE *file= bootstrap_file; - DBUG_ENTER("handle_bootstrap"); + DBUG_ENTER("handle_bootstrap_impl"); #ifndef EMBEDDED_LIBRARY pthread_detach_this_thread(); From 3e1c743d4a100ff13efd030422525b28d1877281 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 22 Oct 2015 07:23:59 +0200 Subject: [PATCH 17/67] MDEV-7656 init_file option does not allow changing passwords allow SET PASSWORD from bootstrap and init-file --- .../r/init_file_set_password-7656.result | 8 ++++++ mysql-test/t/init_file_set_password-7656.test | 26 +++++++++++++++++++ sql/sql_acl.cc | 3 ++- 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 mysql-test/r/init_file_set_password-7656.result create mode 100644 mysql-test/t/init_file_set_password-7656.test diff --git a/mysql-test/r/init_file_set_password-7656.result b/mysql-test/r/init_file_set_password-7656.result new file mode 100644 index 00000000000..e5b3fc75706 --- /dev/null +++ b/mysql-test/r/init_file_set_password-7656.result @@ -0,0 +1,8 @@ +create user foo@localhost; +select user,host,password from mysql.user where user='foo'; +user host password +foo localhost +select user,host,password from mysql.user where user='foo'; +user host password +foo localhost *94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29 +drop user foo@localhost; diff --git a/mysql-test/t/init_file_set_password-7656.test b/mysql-test/t/init_file_set_password-7656.test new file mode 100644 index 00000000000..ecee3924355 --- /dev/null +++ b/mysql-test/t/init_file_set_password-7656.test @@ -0,0 +1,26 @@ +# +# MDEV-7656 init_file option does not allow changing passwords +# +--source include/not_embedded.inc + +create user foo@localhost; + +select user,host,password from mysql.user where user='foo'; + +--write_file $MYSQLTEST_VARDIR/init.file +grant all on *.* to foo@localhost identified by 'test'; +EOF + +--enable_reconnect + +--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + +--shutdown_server 10 +--source include/wait_until_disconnected.inc + +--exec echo "restart:--init-file=$MYSQLTEST_VARDIR/init.file " > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + +--source include/wait_until_connected_again.inc +select user,host,password from mysql.user where user='foo'; + +drop user foo@localhost; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 7d0fefeabd4..e2fb35254af 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2558,7 +2558,8 @@ int check_change_password(THD *thd, const char *host, const char *user, my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--skip-grant-tables"); return(1); } - if (!thd->slave_thread && !thd->security_ctx->priv_user[0]) + if (!thd->slave_thread && !thd->security_ctx->priv_user[0] && + !in_bootstrap) { my_message(ER_PASSWORD_ANONYMOUS_USER, ER(ER_PASSWORD_ANONYMOUS_USER), MYF(0)); From 27328ca1f43e252ed32712210cac1a83d5a0c96d Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 22 Oct 2015 10:27:36 +0200 Subject: [PATCH 18/67] add comment to a test --- mysql-test/suite/roles/ip-6401.test | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mysql-test/suite/roles/ip-6401.test b/mysql-test/suite/roles/ip-6401.test index 34d8553afa3..b7d4b168b75 100644 --- a/mysql-test/suite/roles/ip-6401.test +++ b/mysql-test/suite/roles/ip-6401.test @@ -1,3 +1,6 @@ +# +# MDEV-6401 SET ROLE returning ERROR 1959 Invalid role specification for valid role +# --source include/not_embedded.inc create role r1; create user foo@'127.0.0.1'; From 956e92d90873532fee95581c702f7b76643969ea Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 22 Oct 2015 11:58:54 +0200 Subject: [PATCH 19/67] MDEV-8609 Server crashes in is_invalid_role_name on reloading ACL with a blank role name strip endspaces from the role name in the parser because they'll be lost anyway when the name is stored in the mysql.user.user column (of type CHAR) --- mysql-test/suite/roles/create_and_drop_role.result | 4 ++++ mysql-test/suite/roles/create_and_drop_role.test | 8 ++++++++ sql/sql_yacc.yy | 6 ++++-- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/roles/create_and_drop_role.result b/mysql-test/suite/roles/create_and_drop_role.result index 79c6f412111..d565b888c5f 100644 --- a/mysql-test/suite/roles/create_and_drop_role.result +++ b/mysql-test/suite/roles/create_and_drop_role.result @@ -36,6 +36,10 @@ select user, host, is_role from user where user like 'test%'; user host is_role create role ''; ERROR OP000: Invalid role specification ``. +create role ' '; +ERROR OP000: Invalid role specification ``. +create role 'foo '; +drop role foo; create role r1; drop user r1; ERROR HY000: Operation DROP USER failed for 'r1'@'%' diff --git a/mysql-test/suite/roles/create_and_drop_role.test b/mysql-test/suite/roles/create_and_drop_role.test index 0bf5b744e6b..71d6de7053f 100644 --- a/mysql-test/suite/roles/create_and_drop_role.test +++ b/mysql-test/suite/roles/create_and_drop_role.test @@ -52,6 +52,14 @@ connection default; --error ER_INVALID_ROLE create role ''; +# +# MDEV-8609 Server crashes in is_invalid_role_name on reloading ACL with a blank role name +# +--error ER_INVALID_ROLE +create role ' '; +create role 'foo '; +drop role foo; + # # MDEV-5523 Server crashes on DROP USER # diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index bb8215aaaec..4225f7317b8 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -15170,6 +15170,9 @@ current_role: grant_role: ident_or_text { + CHARSET_INFO *cs= system_charset_info; + /* trim end spaces (as they'll be lost in mysql.user anyway) */ + $1.length= cs->cset->lengthsp(cs, $1.str, $1.length); if ($1.length == 0) { my_error(ER_INVALID_ROLE, MYF(0), ""); @@ -15184,8 +15187,7 @@ grant_role: $$->auth= empty_lex_str; if (check_string_char_length(&$$->user, ER(ER_USERNAME), - username_char_length, - system_charset_info, 0)) + username_char_length, cs, 0)) MYSQL_YYABORT; } | current_role From 6f0754789ca7eee969da84ba3e98d023d7ca812b Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 22 Oct 2015 13:09:38 +0200 Subject: [PATCH 20/67] MDEV-8614 Assertion `status == 0' failed in add_role_user_mapping_action on RENAME USER don't forget to re-examine the current element when updating a HASH --- mysql-test/suite/roles/rebuild_role_grants.result | 6 ++++++ mysql-test/suite/roles/rebuild_role_grants.test | 13 +++++++++++++ sql/sql_acl.cc | 4 ++-- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/roles/rebuild_role_grants.result b/mysql-test/suite/roles/rebuild_role_grants.result index 2817c046ae9..bc68d8ddc9f 100644 --- a/mysql-test/suite/roles/rebuild_role_grants.result +++ b/mysql-test/suite/roles/rebuild_role_grants.result @@ -56,3 +56,9 @@ Host User Role Admin_option localhost root r1 Y drop role r1; drop user u2; +create user foo@localhost; +grant create user on *.* to foo@localhost; +create role look, isp, xxx, ppp; +rename user current_user to nnnn@'%'; +drop role look, isp, xxx, ppp; +drop user nnnn@'%'; diff --git a/mysql-test/suite/roles/rebuild_role_grants.test b/mysql-test/suite/roles/rebuild_role_grants.test index 3ec3577317a..84dbdf78fb8 100644 --- a/mysql-test/suite/roles/rebuild_role_grants.test +++ b/mysql-test/suite/roles/rebuild_role_grants.test @@ -54,3 +54,16 @@ select * from mysql.roles_mapping; drop role r1; drop user u2; + +# +# MDEV-8614 Assertion `status == 0' failed in add_role_user_mapping_action on RENAME USER +# +create user foo@localhost; +grant create user on *.* to foo@localhost; +--connect (con1, localhost, foo,,) +create role look, isp, xxx, ppp; +rename user current_user to nnnn@'%'; +drop role look, isp, xxx, ppp; +connection default; +disconnect con1; +drop user nnnn@'%'; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index e2fb35254af..8316c7b801c 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -8977,8 +8977,7 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, So we need to examine the current element once again, but we don't need to restart the search from the beginning. */ - if (idx != elements) - idx++; + idx++; break; } @@ -9010,6 +9009,7 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, my_hash_update(roles_mappings_hash, (uchar*) role_grant_pair, (uchar*) old_key, old_key_length); + idx++; // see the comment above break; } From 581d85259d2669f5951b2d918ccdf10c0f93a184 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 22 Oct 2015 13:55:55 +0200 Subject: [PATCH 21/67] MDEV-8868 Consider adding a check for libjemalloc version in cmake and/or at runtime add a run-time check for jemalloc >= 2.3 --- storage/tokudb/hatoku_hton.cc | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/storage/tokudb/hatoku_hton.cc b/storage/tokudb/hatoku_hton.cc index a804fc80489..f1a2426c0e3 100644 --- a/storage/tokudb/hatoku_hton.cc +++ b/storage/tokudb/hatoku_hton.cc @@ -356,9 +356,23 @@ static int tokudb_init_func(void *p) { tokudb_hton = (handlerton *) p; #if TOKUDB_CHECK_JEMALLOC - if (tokudb_check_jemalloc && dlsym(RTLD_DEFAULT, "mallctl") == NULL) { - sql_print_error("%s is not initialized because jemalloc is not loaded", tokudb_hton_name); - goto error; + if (tokudb_check_jemalloc) { + typedef int (*mallctl_type)(const char *, void *, size_t *, void *, size_t); + mallctl_type mallctl_func; + mallctl_func= (mallctl_type)dlsym(RTLD_DEFAULT, "mallctl"); + if (!mallctl_func) { + sql_print_error("%s is not initialized because jemalloc is not loaded", tokudb_hton_name); + goto error; + } + char *ver; + size_t len= sizeof(ver); + mallctl_func("version", &ver, &len, NULL, 0); + /* jemalloc 2.2.5 crashes mysql-test */ + if (strcmp(ver, "2.3.") < 0) { + sql_print_error("%s is not initialized because jemalloc is older than 2.3.0", tokudb_hton_name); + goto error; + } + } #endif From df8832caae60de4f7b9ceca808a3f97b92bc22fb Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 22 Oct 2015 15:23:18 +0200 Subject: [PATCH 22/67] MDEV-8883 more cross-compiling fixes don't abort with "XtraDB not supported" if XtraDB was disabled in this build. --- storage/xtradb/CMakeLists.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/storage/xtradb/CMakeLists.txt b/storage/xtradb/CMakeLists.txt index 2f74456e7a7..8daa0374aa5 100644 --- a/storage/xtradb/CMakeLists.txt +++ b/storage/xtradb/CMakeLists.txt @@ -455,12 +455,12 @@ IF(WITH_INNODB) SET(WITH_INNOBASE_STORAGE_ENGINE TRUE) ENDIF() -IF(XTRADB_OK) - MYSQL_ADD_PLUGIN(xtradb ${INNOBASE_SOURCES} STORAGE_ENGINE - DEFAULT - RECOMPILE_FOR_EMBEDDED - LINK_LIBRARIES ${ZLIB_LIBRARY} ${LINKER_SCRIPT}) -ELSE() +MYSQL_ADD_PLUGIN(xtradb ${INNOBASE_SOURCES} STORAGE_ENGINE + DEFAULT + RECOMPILE_FOR_EMBEDDED + LINK_LIBRARIES ${ZLIB_LIBRARY} ${LINKER_SCRIPT}) + +IF(TARGET xtradb AND NOT XTRADB_OK) MESSAGE(FATAL_ERROR "Percona XtraDB is not supported on this platform") ENDIF() From d546d1cc138cc0e6c7d69a55bfee2bebfa4d4c0e Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 23 Oct 2015 18:49:02 +0300 Subject: [PATCH 23/67] Fixed MDEV-8408 Assertion `inited==INDEX' failed in int handler::ha_index_first(uchar*) The crash was because errors from init_read_record_idx() was not taken care of. --- mysql-test/suite/innodb/r/snapshot.result | 8 ++++++ mysql-test/suite/innodb/t/snapshot.test | 18 ++++++++++++ sql/records.cc | 5 +++- sql/records.h | 2 +- sql/sql_delete.cc | 19 +++++++------ sql/sql_update.cc | 34 +++++++++++++---------- 6 files changed, 61 insertions(+), 25 deletions(-) create mode 100644 mysql-test/suite/innodb/r/snapshot.result create mode 100644 mysql-test/suite/innodb/t/snapshot.test diff --git a/mysql-test/suite/innodb/r/snapshot.result b/mysql-test/suite/innodb/r/snapshot.result new file mode 100644 index 00000000000..dcb3d242fc2 --- /dev/null +++ b/mysql-test/suite/innodb/r/snapshot.result @@ -0,0 +1,8 @@ +START TRANSACTION WITH CONSISTENT SNAPSHOT; +CREATE TABLE IF NOT EXISTS t1 (pk INT PRIMARY KEY, i INT, KEY(i)) ENGINE=InnoDB; +UPDATE t1 SET i = 0; +ERROR HY000: Table definition has changed, please retry transaction +UPDATE t1 SET pk = 0; +ERROR HY000: Table definition has changed, please retry transaction +commit; +drop table t1; diff --git a/mysql-test/suite/innodb/t/snapshot.test b/mysql-test/suite/innodb/t/snapshot.test new file mode 100644 index 00000000000..8e3dc76fe54 --- /dev/null +++ b/mysql-test/suite/innodb/t/snapshot.test @@ -0,0 +1,18 @@ + +--source include/have_log_bin.inc +--source include/have_binlog_format_row.inc +--source include/have_innodb.inc + +START TRANSACTION WITH CONSISTENT SNAPSHOT; + +--connect (con1,localhost,root,,test) +CREATE TABLE IF NOT EXISTS t1 (pk INT PRIMARY KEY, i INT, KEY(i)) ENGINE=InnoDB; + +--connection default +--error 1412 +UPDATE t1 SET i = 0; +--error 1412 +UPDATE t1 SET pk = 0; +commit; + +drop table t1; diff --git a/sql/records.cc b/sql/records.cc index bfce2f83967..a37f7a18c11 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -66,10 +66,12 @@ static int rr_index_desc(READ_RECORD *info); @param reverse Scan in the reverse direction */ -void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, +bool init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, bool print_error, uint idx, bool reverse) { int error; + DBUG_ENTER("init_read_record_idx"); + empty_record(table); bzero((char*) info,sizeof(*info)); info->thd= thd; @@ -88,6 +90,7 @@ void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, /* read_record will be changed to rr_index in rr_index_first */ info->read_record= reverse ? rr_index_last : rr_index_first; + DBUG_RETURN(error != 0); } diff --git a/sql/records.h b/sql/records.h index 21477d4a30b..a3f0b5eb084 100644 --- a/sql/records.h +++ b/sql/records.h @@ -76,7 +76,7 @@ public: bool init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form, SQL_SELECT *select, int use_record_cache, bool print_errors, bool disable_rr_cache); -void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, +bool init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, bool print_error, uint idx, bool reverse); void end_read_record(READ_RECORD *info); diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 5292b964576..64f5c85ef22 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -508,17 +508,18 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, free_underlaid_joins(thd, select_lex); DBUG_RETURN(TRUE); } + if (query_plan.index == MAX_KEY || (select && select->quick)) - { - if (init_read_record(&info, thd, table, select, 1, 1, FALSE)) - { - delete select; - free_underlaid_joins(thd, select_lex); - DBUG_RETURN(TRUE); - } - } + error= init_read_record(&info, thd, table, select, 1, 1, FALSE); else - init_read_record_idx(&info, thd, table, 1, query_plan.index, reverse); + error= init_read_record_idx(&info, thd, table, 1, query_plan.index, + reverse); + if (error) + { + delete select; + free_underlaid_joins(thd, select_lex); + DBUG_RETURN(TRUE); + } init_ftfuncs(thd, select_lex, 1); THD_STAGE_INFO(thd, stage_updating); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 03d8e0205ff..2a39e4a1f5e 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -459,7 +459,8 @@ int mysql_update(THD *thd, query_plan.scanned_rows= select? select->records: table->file->stats.records; if (select && select->quick && select->quick->unique_key_range()) - { // Single row select (always "ordered"): Ok to use with key field UPDATE + { + /* Single row select (always "ordered"): Ok to use with key field UPDATE */ need_sort= FALSE; query_plan.index= MAX_KEY; used_key_is_modified= FALSE; @@ -468,7 +469,8 @@ int mysql_update(THD *thd, { ha_rows scanned_limit= query_plan.scanned_rows; query_plan.index= get_index_for_order(order, table, select, limit, - &scanned_limit, &need_sort, &reverse); + &scanned_limit, &need_sort, + &reverse); if (!need_sort) query_plan.scanned_rows= scanned_limit; @@ -481,12 +483,15 @@ int mysql_update(THD *thd, else { if (need_sort) - { // Assign table scan index to check below for modified key fields: + { + /* Assign table scan index to check below for modified key fields: */ query_plan.index= table->file->key_used_on_scan; } if (query_plan.index != MAX_KEY) - { // Check if we are modifying a key that we are used to search with: - used_key_is_modified= is_key_used(table, query_plan.index, table->write_set); + { + /* Check if we are modifying a key that we are used to search with: */ + used_key_is_modified= is_key_used(table, query_plan.index, + table->write_set); } } } @@ -597,19 +602,20 @@ int mysql_update(THD *thd, B. query_plan.index != MAX_KEY B.1 quick select is used, start the scan with init_read_record B.2 quick select is not used, this is full index scan (with LIMIT) - Full index scan must be started with init_read_record_idx + Full index scan must be started with init_read_record_idx */ if (query_plan.index == MAX_KEY || (select && select->quick)) - { - if (init_read_record(&info, thd, table, select, 0, 1, FALSE)) - { - close_cached_file(&tempfile); - goto err; - } - } + error= init_read_record(&info, thd, table, select, 0, 1, FALSE); else - init_read_record_idx(&info, thd, table, 1, query_plan.index, reverse); + error= init_read_record_idx(&info, thd, table, 1, query_plan.index, + reverse); + + if (error) + { + close_cached_file(&tempfile); + goto err; + } THD_STAGE_INFO(thd, stage_searching_rows_for_update); ha_rows tmp_limit= limit; From 2c0bcfff8c8e32a9b70d1090ab34a5f53182ad52 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Sat, 24 Oct 2015 20:16:06 +0400 Subject: [PATCH 24/67] MDEV-8693 Tests connect.bin connect.endian fail on armhf (on Debian build system) --- storage/connect/tabfix.cpp | 12 ++++++------ storage/connect/value.h | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/storage/connect/tabfix.cpp b/storage/connect/tabfix.cpp index acd548c86ab..55c254f41ea 100644 --- a/storage/connect/tabfix.cpp +++ b/storage/connect/tabfix.cpp @@ -511,29 +511,29 @@ void BINCOL::ReadColumn(PGLOBAL g) switch (Fmt) { case 'X': // Standard not converted values if (Eds && IsTypeChar(Buf_Type)) - Value->SetValue(*(longlong*)p); + Value->SetValueNonAligned(p); else Value->SetBinValue(p); break; case 'S': // Short integer - Value->SetValue(*(short*)p); + Value->SetValueNonAligned(p); break; case 'T': // Tiny integer Value->SetValue(*p); break; case 'I': // Integer - Value->SetValue(*(int*)p); + Value->SetValueNonAligned(p); break; case 'G': // Large (great) integer - Value->SetValue(*(longlong*)p); + Value->SetValueNonAligned(p); break; case 'F': // Float case 'R': // Real - Value->SetValue((double)*(float*)p); + Value->SetValueNonAligned(p); break; case 'D': // Double - Value->SetValue(*(double*)p); + Value->SetValueNonAligned(p); break; case 'C': // Text if (Value->SetValue_char(p, Long)) { diff --git a/storage/connect/value.h b/storage/connect/value.h index 780917c9962..471da851423 100644 --- a/storage/connect/value.h +++ b/storage/connect/value.h @@ -116,6 +116,26 @@ class DllExport VALUE : public BLOCK { virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op); virtual bool FormatValue(PVAL vp, char *fmt) = 0; + /** + Set value from a non-aligned in-memory value in the machine byte order. + TYPE can be either of: + - int, short, longlong + - uint, ushort, ulonglong + - float, double + @param - a pointer to a non-aligned value of type TYPE. + */ + template + void SetValueNonAligned(const char *p) + { +#if defined(__i386__) || defined(__x86_64__) + SetValue(*((TYPE*) p)); // x86 can cast non-aligned memory directly +#else + TYPE tmp; // a slower version for non-x86 platforms + memcpy(&tmp, p, sizeof(tmp)); + SetValue(tmp); +#endif + } + protected: virtual bool SetConstFormat(PGLOBAL, FORMAT&) = 0; const char *GetXfmt(void); From fb8713385f514da0b77d1212f2035a6d5678561e Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 23 Oct 2015 11:31:18 +0200 Subject: [PATCH 25/67] remove unneded #include's that had a dubious explanation --- include/decimal.h | 8 ++++++++ sql/filesort.cc | 1 - sql/hostname.cc | 1 + sql/item.cc | 1 - sql/item.h | 1 - sql/key.cc | 1 - sql/lock.cc | 1 - sql/log.h | 1 - sql/protocol.cc | 1 - sql/rpl_injector.cc | 1 - sql/rpl_mi.cc | 1 - sql/rpl_record_old.cc | 1 - sql/sql_base.h | 1 - sql/sql_class.cc | 1 - sql/sql_class.h | 3 --- sql/sql_connect.cc | 1 - sql/sql_const.h | 4 +++- sql/sql_handler.cc | 1 - sql/sql_insert.cc | 1 - sql/sql_lex.cc | 1 - sql/sql_manager.cc | 1 - sql/sql_parse.cc | 1 - sql/sql_partition.cc | 1 - sql/sql_profile.cc | 1 - sql/sql_time.cc | 1 - sql/sql_trigger.h | 2 ++ sql/sql_update.cc | 1 - sql/sql_yacc.yy | 1 - sql/table.cc | 1 - storage/federatedx/federatedx_io_mysql.cc | 1 + 30 files changed, 15 insertions(+), 28 deletions(-) diff --git a/include/decimal.h b/include/decimal.h index 935d341437d..2adeb824318 100644 --- a/include/decimal.h +++ b/include/decimal.h @@ -16,6 +16,10 @@ #ifndef _decimal_h #define _decimal_h +#ifdef __cplusplus +extern "C" { +#endif + typedef enum {TRUNCATE=0, HALF_EVEN, HALF_UP, CEILING, FLOOR} decimal_round_mode; @@ -112,5 +116,9 @@ void max_decimal(int precision, int frac, decimal_t *to); #define E_DEC_ERROR 31 #define E_DEC_FATAL_ERROR 30 +#ifdef __cplusplus +} +#endif + #endif diff --git a/sql/filesort.cc b/sql/filesort.cc index a545bb623c0..6ad7bee48c6 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -25,7 +25,6 @@ #include #include "sql_priv.h" #include "filesort.h" -#include "unireg.h" // REQUIRED by other includes #ifdef HAVE_STDDEF_H #include /* for macro offsetof */ #endif diff --git a/sql/hostname.cc b/sql/hostname.cc index 1879d056623..f08ae247398 100644 --- a/sql/hostname.cc +++ b/sql/hostname.cc @@ -26,6 +26,7 @@ */ #include #include "sql_priv.h" +#include "unireg.h" // SPECIAL_NO_HOST_CACHE #include "hostname.h" #include "my_global.h" #ifndef __WIN__ diff --git a/sql/item.cc b/sql/item.cc index 934846c4815..90a8777d8f7 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -21,7 +21,6 @@ #endif #include /* NO_EMBEDDED_ACCESS_CHECKS */ #include "sql_priv.h" -#include "unireg.h" // REQUIRED: for other includes #include #include #include "my_dir.h" diff --git a/sql/item.h b/sql/item.h index 353c9e0f6bc..ec952f3f5a6 100644 --- a/sql/item.h +++ b/sql/item.h @@ -25,7 +25,6 @@ #include "sql_priv.h" /* STRING_BUFFER_USUAL_SIZE */ #include "unireg.h" #include "sql_const.h" /* RAND_TABLE_BIT, MAX_FIELD_NAME */ -#include "unireg.h" // REQUIRED: for other includes #include "thr_malloc.h" /* sql_calloc */ #include "field.h" /* Derivation */ diff --git a/sql/key.cc b/sql/key.cc index e3787ea7869..aaaea9391c6 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -18,7 +18,6 @@ #include #include "sql_priv.h" -#include "unireg.h" // REQUIRED: by includes later #include "key.h" // key_rec_cmp #include "field.h" // Field diff --git a/sql/lock.cc b/sql/lock.cc index e713990bd58..614341fcc43 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -77,7 +77,6 @@ #include #include "sql_priv.h" #include "debug_sync.h" -#include "unireg.h" // REQUIRED: for other includes #include "lock.h" #include "sql_base.h" // close_tables_for_reopen #include "sql_parse.h" // is_log_table_write_query diff --git a/sql/log.h b/sql/log.h index 48970f7452a..31a1d102bf7 100644 --- a/sql/log.h +++ b/sql/log.h @@ -17,7 +17,6 @@ #ifndef LOG_H #define LOG_H -#include "unireg.h" // REQUIRED: for other includes #include "handler.h" /* my_xid */ class Relay_log_info; diff --git a/sql/protocol.cc b/sql/protocol.cc index a6d67fd4a91..c1614f4e7e4 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -27,7 +27,6 @@ #include #include "sql_priv.h" -#include "unireg.h" // REQUIRED: for other includes #include "protocol.h" #include "sql_class.h" // THD #include diff --git a/sql/rpl_injector.cc b/sql/rpl_injector.cc index 19b193729fd..94b081bf4f4 100644 --- a/sql/rpl_injector.cc +++ b/sql/rpl_injector.cc @@ -15,7 +15,6 @@ #include #include "sql_priv.h" -#include "unireg.h" // REQUIRED by later includes #include "rpl_injector.h" #include "transaction.h" #include "sql_parse.h" // begin_trans, end_trans, COMMIT diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index 47490648a43..ae6cc1ac0a2 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -17,7 +17,6 @@ #include // For HAVE_REPLICATION #include "sql_priv.h" #include -#include "unireg.h" // REQUIRED by other includes #include "rpl_mi.h" #include "slave.h" // SLAVE_MAX_HEARTBEAT_PERIOD #include "strfunc.h" diff --git a/sql/rpl_record_old.cc b/sql/rpl_record_old.cc index 061fab78dbd..5b876373b9c 100644 --- a/sql/rpl_record_old.cc +++ b/sql/rpl_record_old.cc @@ -15,7 +15,6 @@ #include #include "sql_priv.h" -#include "unireg.h" // REQUIRED by other includes #include "rpl_rli.h" #include "rpl_record_old.h" #include "log_event.h" // Log_event_type diff --git a/sql/sql_base.h b/sql/sql_base.h index a6d90199860..aa4a041fc10 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -16,7 +16,6 @@ #ifndef SQL_BASE_INCLUDED #define SQL_BASE_INCLUDED -#include "unireg.h" // REQUIRED: for other includes #include "sql_trigger.h" /* trg_event_type */ #include "sql_class.h" /* enum_mark_columns */ #include "mysqld.h" /* key_map */ diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 978adf6a353..583abee360f 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -30,7 +30,6 @@ #include /* NO_EMBEDDED_ACCESS_CHECKS */ #include "sql_priv.h" -#include "unireg.h" // REQUIRED: for other includes #include "sql_class.h" #include "sql_cache.h" // query_cache_abort #include "sql_base.h" // close_thread_tables diff --git a/sql/sql_class.h b/sql/sql_class.h index f577935f545..b2fa6840439 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -21,9 +21,6 @@ /* Classes in mysql */ #include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */ -#ifdef MYSQL_SERVER -#include "unireg.h" // REQUIRED: for other includes -#endif #include #include "sql_const.h" #include diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 0202b4493ac..4d2c48c83cc 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -28,7 +28,6 @@ #include "sql_audit.h" #include "sql_connect.h" #include "probes_mysql.h" -#include "unireg.h" // REQUIRED: for other includes #include "sql_parse.h" // sql_command_flags, // execute_init_command, // do_command diff --git a/sql/sql_const.h b/sql/sql_const.h index 9110902cde7..5c3a6d9a7cf 100644 --- a/sql/sql_const.h +++ b/sql/sql_const.h @@ -17,12 +17,14 @@ @file File containing constants that can be used throughout the server. - @note This file shall not contain any includes of any kinds. + @note This file shall not contain or include any declarations of any kinds. */ #ifndef SQL_CONST_INCLUDED #define SQL_CONST_INCLUDED +#include + #define LIBLEN FN_REFLEN-FN_LEN /* Max l{ngd p} dev */ /* extra 4+4 bytes for slave tmp tables */ #define MAX_DBKEY_LENGTH (NAME_LEN*2+1+1+4+4) diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index c2d4c32ab71..5fc7c20d409 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -55,7 +55,6 @@ #include #include "sql_priv.h" #include "sql_handler.h" -#include "unireg.h" // REQUIRED: for other includes #include "sql_base.h" // close_thread_tables #include "lock.h" // mysql_unlock_tables #include "key.h" // key_copy diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 522f55cd102..aa748c6d72c 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -58,7 +58,6 @@ #include /* NO_EMBEDDED_ACCESS_CHECKS */ #include "sql_priv.h" -#include "unireg.h" // REQUIRED: for other includes #include "sql_insert.h" #include "sql_update.h" // compare_record #include "sql_base.h" // close_thread_tables diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 9d71b1f1226..b25f8d0dae6 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -20,7 +20,6 @@ #define MYSQL_LEX 1 #include #include "sql_priv.h" -#include "unireg.h" // REQUIRED: for other includes #include "sql_class.h" // sql_lex.h: SQLCOM_END #include "sql_lex.h" #include "sql_parse.h" // add_to_list diff --git a/sql/sql_manager.cc b/sql/sql_manager.cc index c6c465aa4e2..8cf849b97d0 100644 --- a/sql/sql_manager.cc +++ b/sql/sql_manager.cc @@ -24,7 +24,6 @@ #include #include "sql_priv.h" #include "sql_manager.h" -#include "unireg.h" // REQUIRED: for other includes #include "sql_base.h" // flush_tables static bool volatile manager_thread_in_use; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 21d006537ac..ee52dbe58a1 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -17,7 +17,6 @@ #define MYSQL_LEX 1 #include #include "sql_priv.h" -#include "unireg.h" // REQUIRED: for other includes #include "sql_parse.h" // sql_kill, *_precheck, *_prepare #include "lock.h" // try_transactional_lock, // check_transactional_lock, diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index f0fde223984..be7824aae9e 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -49,7 +49,6 @@ #define MYSQL_LEX 1 #include #include "sql_priv.h" -#include "unireg.h" // REQUIRED: for other includes #include "sql_partition.h" #include "key.h" // key_restore #include "sql_parse.h" // parse_sql diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc index 26d515842ed..6b30dd28a51 100644 --- a/sql/sql_profile.cc +++ b/sql/sql_profile.cc @@ -31,7 +31,6 @@ #include #include "sql_priv.h" -#include "unireg.h" // REQUIRED: for other includes #include "sql_profile.h" #include #include "sql_show.h" // schema_table_store_record diff --git a/sql/sql_time.cc b/sql/sql_time.cc index ca689d55a2b..f2596401c2e 100644 --- a/sql/sql_time.cc +++ b/sql/sql_time.cc @@ -19,7 +19,6 @@ #include #include "sql_priv.h" -#include "unireg.h" // REQUIRED by other includes #include "sql_time.h" #include "tztime.h" // struct Time_zone #include "sql_class.h" // THD diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h index 52892550d35..7dfe8939945 100644 --- a/sql/sql_trigger.h +++ b/sql/sql_trigger.h @@ -17,6 +17,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + /* Forward declarations */ class Item_trigger_field; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 2a39e4a1f5e..d3d222620a8 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -22,7 +22,6 @@ #include /* NO_EMBEDDED_ACCESS_CHECKS */ #include "sql_priv.h" -#include "unireg.h" // REQUIRED: for other includes #include "sql_update.h" #include "sql_cache.h" // query_cache_* #include "sql_base.h" // close_tables_for_reopen diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 4225f7317b8..c6797278e02 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -35,7 +35,6 @@ #define Select Lex->current_select #include #include "sql_priv.h" -#include "unireg.h" // REQUIRED: for other includes #include "sql_parse.h" /* comp_*_creator */ #include "sql_table.h" /* primary_key_name */ #include "sql_partition.h" /* mem_alloc_error, partition_info, HASH_PARTITION */ diff --git a/sql/table.cc b/sql/table.cc index da6c4ccf42f..3f63e5b45c7 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -19,7 +19,6 @@ #include /* NO_EMBEDDED_ACCESS_CHECKS */ #include "sql_priv.h" -#include "unireg.h" // REQUIRED: for other includes #include "table.h" #include "key.h" // find_ref_key #include "sql_table.h" // build_table_filename, diff --git a/storage/federatedx/federatedx_io_mysql.cc b/storage/federatedx/federatedx_io_mysql.cc index 1ff6abc4c77..f9de6e8af3b 100644 --- a/storage/federatedx/federatedx_io_mysql.cc +++ b/storage/federatedx/federatedx_io_mysql.cc @@ -34,6 +34,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ha_federatedx.h" #include "m_string.h" +#include "mysqld_error.h" #include "sql_servers.h" #ifdef USE_PRAGMA_IMPLEMENTATION From 84da1547e6ccc25daa0e7a9b11ae51c51629a923 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 23 Oct 2015 22:21:50 +0200 Subject: [PATCH 26/67] MDEV-8883 more cross-compiling fixes use CHECK_C_SOURCE_COMPILES for atomic tests if cross-compiling (continue to use CHECK_C_SOURCE_RUNS otherwise) --- storage/innobase/CMakeLists.txt | 68 +++++++++++++++++++-------------- storage/xtradb/CMakeLists.txt | 66 ++++++++++++++++++-------------- 2 files changed, 77 insertions(+), 57 deletions(-) diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt index 711672f5363..df60ba0d16f 100644 --- a/storage/innobase/CMakeLists.txt +++ b/storage/innobase/CMakeLists.txt @@ -19,6 +19,20 @@ INCLUDE(CheckFunctionExists) INCLUDE(CheckCSourceCompiles) INCLUDE(CheckCSourceRuns) +IF(CMAKE_CROSSCOMPILING) + # Use CHECK_C_SOURCE_COMPILES instead of CHECK_C_SOURCE_RUNS when + # cross-compiling. Not as precise, but usually good enough. + # This only make sense for atomic tests in this file, this trick doesn't + # work in a general case. + MACRO(CHECK_C_SOURCE SOURCE VAR) + CHECK_C_SOURCE_COMPILES("${SOURCE}" "${VAR}") + ENDMACRO() +ELSE() + MACRO(CHECK_C_SOURCE SOURCE VAR) + CHECK_C_SOURCE_RUNS("${SOURCE}" "${VAR}") + ENDMACRO() +ENDIF() + # OS tests IF(UNIX) IF(CMAKE_SYSTEM_NAME STREQUAL "Linux") @@ -60,15 +74,14 @@ SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DUNIV_DEBUG -DUNIV_SYNC_DEB CHECK_FUNCTION_EXISTS(sched_getcpu HAVE_SCHED_GETCPU) IF(NOT MSVC) -# either define HAVE_IB_GCC_ATOMIC_BUILTINS or not -IF(NOT CMAKE_CROSSCOMPILING) + # either define HAVE_IB_GCC_ATOMIC_BUILTINS or not # workaround for gcc 4.1.2 RHEL5/x86, gcc atomic ops only work under -march=i686 IF(CMAKE_SYSTEM_PROCESSOR STREQUAL "i686" AND CMAKE_COMPILER_IS_GNUCC AND CMAKE_C_COMPILER_VERSION VERSION_LESS "4.1.3") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i686") ENDIF() - CHECK_C_SOURCE_RUNS( + CHECK_C_SOURCE( " int main() { @@ -99,7 +112,7 @@ IF(NOT CMAKE_CROSSCOMPILING) }" HAVE_IB_GCC_ATOMIC_BUILTINS ) - CHECK_C_SOURCE_RUNS( + CHECK_C_SOURCE( " int main() { @@ -115,7 +128,7 @@ IF(NOT CMAKE_CROSSCOMPILING) }" HAVE_IB_GCC_ATOMIC_BUILTINS_BYTE ) - CHECK_C_SOURCE_RUNS( + CHECK_C_SOURCE( "#include int main() { @@ -135,7 +148,7 @@ IF(NOT CMAKE_CROSSCOMPILING) }" HAVE_IB_GCC_ATOMIC_BUILTINS_64 ) - CHECK_C_SOURCE_RUNS( + CHECK_C_SOURCE( "#include int main() { @@ -144,7 +157,7 @@ IF(NOT CMAKE_CROSSCOMPILING) }" HAVE_IB_GCC_SYNC_SYNCHRONISE ) - CHECK_C_SOURCE_RUNS( + CHECK_C_SOURCE( "#include int main() { @@ -154,7 +167,7 @@ IF(NOT CMAKE_CROSSCOMPILING) }" HAVE_IB_GCC_ATOMIC_THREAD_FENCE ) - CHECK_C_SOURCE_RUNS( + CHECK_C_SOURCE( "#include int main() { @@ -166,7 +179,6 @@ IF(NOT CMAKE_CROSSCOMPILING) }" HAVE_IB_GCC_ATOMIC_TEST_AND_SET ) -ENDIF() IF(HAVE_IB_GCC_ATOMIC_BUILTINS) ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_BUILTINS=1) @@ -192,28 +204,27 @@ IF(HAVE_IB_GCC_ATOMIC_TEST_AND_SET) ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_TEST_AND_SET=1) ENDIF() - # either define HAVE_IB_ATOMIC_PTHREAD_T_GCC or not -IF(NOT CMAKE_CROSSCOMPILING) - CHECK_C_SOURCE_RUNS( - " - #include - #include +# either define HAVE_IB_ATOMIC_PTHREAD_T_GCC or not +CHECK_C_SOURCE( +" +#include +#include - int main() { - pthread_t x1; - pthread_t x2; - pthread_t x3; +int main() { + pthread_t x1; + pthread_t x2; + pthread_t x3; - memset(&x1, 0x0, sizeof(x1)); - memset(&x2, 0x0, sizeof(x2)); - memset(&x3, 0x0, sizeof(x3)); + memset(&x1, 0x0, sizeof(x1)); + memset(&x2, 0x0, sizeof(x2)); + memset(&x3, 0x0, sizeof(x3)); - __sync_bool_compare_and_swap(&x1, x2, x3); + __sync_bool_compare_and_swap(&x1, x2, x3); + + return(0); +}" +HAVE_IB_ATOMIC_PTHREAD_T_GCC) - return(0); - }" - HAVE_IB_ATOMIC_PTHREAD_T_GCC) -ENDIF() IF(HAVE_IB_ATOMIC_PTHREAD_T_GCC) ADD_DEFINITIONS(-DHAVE_IB_ATOMIC_PTHREAD_T_GCC=1) ENDIF() @@ -244,7 +255,6 @@ IF(CMAKE_SYSTEM_NAME STREQUAL "SunOS") ADD_DEFINITIONS(-DHAVE_IB_SOLARIS_ATOMICS=1) ENDIF() - IF(NOT CMAKE_CROSSCOMPILING) # either define HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS or not CHECK_C_SOURCE_COMPILES( " #include @@ -283,7 +293,7 @@ IF(CMAKE_SYSTEM_NAME STREQUAL "SunOS") return(0); }" HAVE_IB_MACHINE_BARRIER_SOLARIS) - ENDIF() + IF(HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS) ADD_DEFINITIONS(-DHAVE_IB_ATOMIC_PTHREAD_T_SOLARIS=1) ENDIF() diff --git a/storage/xtradb/CMakeLists.txt b/storage/xtradb/CMakeLists.txt index 8daa0374aa5..fa7c9df9fe1 100644 --- a/storage/xtradb/CMakeLists.txt +++ b/storage/xtradb/CMakeLists.txt @@ -19,6 +19,20 @@ INCLUDE(CheckFunctionExists) INCLUDE(CheckCSourceCompiles) INCLUDE(CheckCSourceRuns) +IF(CMAKE_CROSSCOMPILING) + # Use CHECK_C_SOURCE_COMPILES instead of CHECK_C_SOURCE_RUNS when + # cross-compiling. Not as precise, but usually good enough. + # This only make sense for atomic tests in this file, this trick doesn't + # work in a general case. + MACRO(CHECK_C_SOURCE SOURCE VAR) + CHECK_C_SOURCE_COMPILES("${SOURCE}" "${VAR}") + ENDMACRO() +ELSE() + MACRO(CHECK_C_SOURCE SOURCE VAR) + CHECK_C_SOURCE_RUNS("${SOURCE}" "${VAR}") + ENDMACRO() +ENDIF() + # OS tests IF(UNIX) IF(CMAKE_SYSTEM_NAME STREQUAL "Linux") @@ -63,15 +77,14 @@ SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DUNIV_DEBUG -DUNIV_SYNC_DEB CHECK_FUNCTION_EXISTS(sched_getcpu HAVE_SCHED_GETCPU) IF(NOT MSVC) -# either define HAVE_IB_GCC_ATOMIC_BUILTINS or not -IF(NOT CMAKE_CROSSCOMPILING) + # either define HAVE_IB_GCC_ATOMIC_BUILTINS or not # workaround for gcc 4.1.2 RHEL5/x86, gcc atomic ops only work under -march=i686 IF(CMAKE_SYSTEM_PROCESSOR STREQUAL "i686" AND CMAKE_COMPILER_IS_GNUCC AND CMAKE_C_COMPILER_VERSION VERSION_LESS "4.1.3") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i686") ENDIF() - CHECK_C_SOURCE_RUNS( + CHECK_C_SOURCE( " int main() { @@ -102,7 +115,7 @@ IF(NOT CMAKE_CROSSCOMPILING) }" HAVE_IB_GCC_ATOMIC_BUILTINS ) - CHECK_C_SOURCE_RUNS( + CHECK_C_SOURCE( " int main() { @@ -118,7 +131,7 @@ IF(NOT CMAKE_CROSSCOMPILING) }" HAVE_IB_GCC_ATOMIC_BUILTINS_BYTE ) - CHECK_C_SOURCE_RUNS( + CHECK_C_SOURCE( "#include int main() { @@ -138,7 +151,7 @@ IF(NOT CMAKE_CROSSCOMPILING) }" HAVE_IB_GCC_ATOMIC_BUILTINS_64 ) - CHECK_C_SOURCE_RUNS( + CHECK_C_SOURCE( "#include int main() { @@ -147,7 +160,7 @@ IF(NOT CMAKE_CROSSCOMPILING) }" HAVE_IB_GCC_SYNC_SYNCHRONISE ) - CHECK_C_SOURCE_RUNS( + CHECK_C_SOURCE( "#include int main() { @@ -157,7 +170,6 @@ IF(NOT CMAKE_CROSSCOMPILING) }" HAVE_IB_GCC_ATOMIC_THREAD_FENCE ) -ENDIF() IF(HAVE_IB_GCC_ATOMIC_BUILTINS) ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_BUILTINS=1) @@ -180,28 +192,27 @@ IF(HAVE_IB_GCC_ATOMIC_THREAD_FENCE) ADD_DEFINITIONS(-DHAVE_IB_GCC_ATOMIC_THREAD_FENCE=1) ENDIF() - # either define HAVE_IB_ATOMIC_PTHREAD_T_GCC or not -IF(NOT CMAKE_CROSSCOMPILING) - CHECK_C_SOURCE_RUNS( - " - #include - #include +# either define HAVE_IB_ATOMIC_PTHREAD_T_GCC or not +CHECK_C_SOURCE( +" +#include +#include - int main() { - pthread_t x1; - pthread_t x2; - pthread_t x3; +int main() { + pthread_t x1; + pthread_t x2; + pthread_t x3; - memset(&x1, 0x0, sizeof(x1)); - memset(&x2, 0x0, sizeof(x2)); - memset(&x3, 0x0, sizeof(x3)); + memset(&x1, 0x0, sizeof(x1)); + memset(&x2, 0x0, sizeof(x2)); + memset(&x3, 0x0, sizeof(x3)); - __sync_bool_compare_and_swap(&x1, x2, x3); + __sync_bool_compare_and_swap(&x1, x2, x3); + + return(0); +}" +HAVE_IB_ATOMIC_PTHREAD_T_GCC) - return(0); - }" - HAVE_IB_ATOMIC_PTHREAD_T_GCC) -ENDIF() IF(HAVE_IB_ATOMIC_PTHREAD_T_GCC) ADD_DEFINITIONS(-DHAVE_IB_ATOMIC_PTHREAD_T_GCC=1) ENDIF() @@ -233,7 +244,6 @@ IF(CMAKE_SYSTEM_NAME STREQUAL "SunOS") SET(XTRADB_OK 1) ENDIF() - IF(NOT CMAKE_CROSSCOMPILING) # either define HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS or not CHECK_C_SOURCE_COMPILES( " #include @@ -272,7 +282,7 @@ IF(CMAKE_SYSTEM_NAME STREQUAL "SunOS") return(0); }" HAVE_IB_MACHINE_BARRIER_SOLARIS) - ENDIF() + IF(HAVE_IB_ATOMIC_PTHREAD_T_SOLARIS) ADD_DEFINITIONS(-DHAVE_IB_ATOMIC_PTHREAD_T_SOLARIS=1) ENDIF() From 6a28882b57497b7c167577b2cdc03c7193779b71 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 24 Oct 2015 20:06:59 +0200 Subject: [PATCH 27/67] merge commit 02b00b154 Author: Marc Alff Date: Thu Jul 30 11:17:50 2015 +0200 Bug#21528683 SLOWDOWN CAUSED BY MEMSET IN SQL_DIGEST_STORAGE.RESET() --- sql/sql_digest.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sql/sql_digest.h b/sql/sql_digest.h index ce159283d4d..eaf74b9542e 100644 --- a/sql/sql_digest.h +++ b/sql/sql_digest.h @@ -41,6 +41,9 @@ struct sql_digest_storage For Example: SELECT * FROM T1; <SELECT_TOKEN> <*> <FROM_TOKEN> <ID_TOKEN> <2> <T1> + + @note Only the first @c m_byte_count bytes are initialized, + out of @c m_token_array_length. */ unsigned char *m_token_array; /* Length of the token array to be considered for DIGEST_TEXT calculation. */ @@ -63,10 +66,6 @@ struct sql_digest_storage m_full= false; m_byte_count= 0; m_charset_number= 0; - if (m_token_array_length > 0) - { - memset(m_token_array, 0, m_token_array_length); - } memset(m_md5, 0, MD5_HASH_SIZE); } From c9185225cba8bb6a2a6745d98a168efe6dfaddcd Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Sun, 25 Oct 2015 22:45:48 +0400 Subject: [PATCH 28/67] MDEV-8358 ALTER TABLE .. ADD PRIMARY KEY IF NOT EXISTS -> ERROR 1068 (42000): Multiple primary key defined Checks for multiple primary keys added. --- mysql-test/r/alter_table.result | 9 +++++++++ mysql-test/t/alter_table.test | 13 +++++++++++++ sql/sql_table.cc | 11 +++++++++++ 3 files changed, 33 insertions(+) diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index 5df0c2e3c96..e572fdb197c 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -2012,3 +2012,12 @@ t1 CREATE TABLE `t1` ( UNIQUE KEY `idx` (`i`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t1; +CREATE TABLE t1 ( +`event_id` bigint(20) unsigned NOT NULL DEFAULT '0', +`market_id` bigint(20) unsigned NOT NULL DEFAULT '0', +PRIMARY KEY (`event_id`,`market_id`) +); +ALTER TABLE t1 ADD PRIMARY KEY IF NOT EXISTS event_id (event_id,market_id); +Warnings: +Note 1061 Multiple primary key defined +DROP TABLE t1; diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index 4dde3ed6971..05d915ec478 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -1699,3 +1699,16 @@ alter table t1 add unique index if not exists idx(i); alter table t1 add unique index if not exists idx(i); show create table t1; DROP TABLE t1; + +# +# MDEV-8358 ADD PRIMARY KEY IF NOT EXISTS -> ERROR 1068 (42000): Multiple primary key +# + +CREATE TABLE t1 ( + `event_id` bigint(20) unsigned NOT NULL DEFAULT '0', + `market_id` bigint(20) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`event_id`,`market_id`) + ); +ALTER TABLE t1 ADD PRIMARY KEY IF NOT EXISTS event_id (event_id,market_id); +DROP TABLE t1; + diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 5ad4ceb9c35..e0f7184b0e8 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5846,6 +5846,16 @@ drop_create_field: { if (!key->create_if_not_exists) continue; + + /* Check if the table already has a PRIMARY KEY */ + if (key->type == Key::PRIMARY && + table->s->primary_key != MAX_KEY) + { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, + ER_DUP_KEYNAME, ER(ER_MULTIPLE_PRI_KEY)); + goto remove_key_no_warn; + } + /* If the name of the key is not specified, */ /* let us check the name of the first key part. */ if ((keyname= key->name.str) == NULL) @@ -5912,6 +5922,7 @@ drop_create_field: remove_key: push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, ER_DUP_KEYNAME, ER(ER_DUP_KEYNAME), keyname); +remove_key_no_warn: key_it.remove(); if (key->type == Key::FOREIGN_KEY) { From e4f9d20d7c0359aadaf212346f7b4517e7efa5d7 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Fri, 23 Oct 2015 15:06:43 +0400 Subject: [PATCH 29/67] MDEV-8498 - mysql_secure_installation can't find "mysql" in basedir mysql_secure_installation used incorrect path while looking up for "mysql" client tool: $basedir/$basedir/bin instead of $basedir/bin. This patch adapts "my_print_defaults" lookup algorithm for "mysql" client tool. --- scripts/mysql_secure_installation.sh | 32 +++++++++++----------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/scripts/mysql_secure_installation.sh b/scripts/mysql_secure_installation.sh index d91e31cda48..82ea1b60a17 100644 --- a/scripts/mysql_secure_installation.sh +++ b/scripts/mysql_secure_installation.sh @@ -24,7 +24,6 @@ rootpass="" echo_n= echo_c= basedir= -bindir= defaults_file= defaults_extra_file= no_defaults= @@ -159,8 +158,15 @@ then cannot_find_file my_print_defaults $basedir/bin $basedir/extra exit 1 fi + mysql_command=`find_in_basedir mysql bin` + if test -z "$mysql_command" + then + cannot_find_file mysql $basedir/bin + exit 1 + fi else print_defaults="@bindir@/my_print_defaults" + mysql_command="@bindir@/mysql" fi if test ! -x "$print_defaults" @@ -169,29 +175,17 @@ then exit 1 fi +if test ! -x "$mysql_command" +then + cannot_find_file "$mysql_command" + exit 1 +fi + # Now we can get arguments from the group [client] and [client-server] # in the my.cfg file, then re-run to merge with command line arguments. parse_arguments `$print_defaults $defaults_file $defaults_extra_file $no_defaults client client-server client-mariadb` parse_arguments PICK-ARGS-FROM-ARGV "$@" -# Configure paths to support files -if test -n "$basedir" -then - bindir="$basedir/bin" -elif test -f "./bin/mysql" - then - bindir="./bin" -else - bindir="@bindir@" -fi - -mysql_command=`find_in_basedir mysql $bindir` -if test -z "$mysql_command" -then - cannot_find_file mysql $bindir - exit 1 -fi - set_echo_compat() { case `echo "testing\c"`,`echo -n testing` in *c*,-n*) echo_n= echo_c= ;; From d6480f49ffb8a2a6e63915a55aa8bd067b0850e5 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Sun, 11 Oct 2015 10:32:44 +0200 Subject: [PATCH 30/67] Fixed Fedora 22 package build failure. Since MariaDB packages have absolute paths, they are marked as not relocatable by setting CPACK_RPM_PACKAGE_RELOCATABLE. According to logics of recent CPackRPM it is not enough: one needs to set CPACK_PACKAGE_RELOCATABLE additionally. --- cmake/cpack_rpm.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index b936e2c0983..78550fcc6a8 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -34,6 +34,7 @@ SET(CPACK_PACKAGE_FILE_NAME "${CPACK_RPM_PACKAGE_NAME}-${VERSION}-${RPM}-${CMAKE SET(CPACK_RPM_PACKAGE_RELEASE "1%{?dist}") SET(CPACK_RPM_PACKAGE_LICENSE "GPL") SET(CPACK_RPM_PACKAGE_RELOCATABLE FALSE) +SET(CPACK_PACKAGE_RELOCATABLE FALSE) SET(CPACK_RPM_PACKAGE_GROUP "Applications/Databases") SET(CPACK_RPM_PACKAGE_URL "http://mariadb.org") SET(CPACK_RPM_PACKAGE_SUMMARY "MariaDB: a very fast and robust SQL database server") From 13884cf206c7e1a828748173a4d723cfe186fd8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 27 Oct 2015 13:00:15 +0200 Subject: [PATCH 31/67] MDEV-8696: Adding indexes on empty table is slow with large innodb_sort_buffer_size. Analysis: Current implementation will write and read at least one block (sort_buffer_size bytes) from disk / index even if that block does not contain any records. Fix: Avoid writing / reading empty blocks to temporary files (disk). --- .../innodb/r/innodb-alter-filewrite.result | 30 ++++++++++++ .../suite/innodb/r/innodb_monitor.result | 9 ++++ .../innodb/t/innodb-alter-filewrite.test | 32 +++++++++++++ .../r/innodb_monitor_disable_basic.result | 9 ++++ .../r/innodb_monitor_enable_basic.result | 9 ++++ .../r/innodb_monitor_reset_all_basic.result | 9 ++++ .../r/innodb_monitor_reset_basic.result | 9 ++++ storage/innobase/handler/ha_innodb.cc | 8 +++- storage/innobase/include/srv0mon.h | 4 ++ storage/innobase/include/srv0srv.h | 14 +++++- storage/innobase/row/row0merge.cc | 47 ++++++++++++------- storage/innobase/srv/srv0mon.cc | 34 ++++++++++++++ storage/innobase/srv/srv0srv.cc | 6 ++- storage/xtradb/handler/ha_innodb.cc | 8 +++- storage/xtradb/include/srv0mon.h | 4 ++ storage/xtradb/include/srv0srv.h | 12 ++++- storage/xtradb/row/row0merge.cc | 47 ++++++++++++------- storage/xtradb/srv/srv0mon.cc | 34 ++++++++++++++ storage/xtradb/srv/srv0srv.cc | 6 ++- 19 files changed, 293 insertions(+), 38 deletions(-) create mode 100644 mysql-test/suite/innodb/r/innodb-alter-filewrite.result create mode 100644 mysql-test/suite/innodb/t/innodb-alter-filewrite.test diff --git a/mysql-test/suite/innodb/r/innodb-alter-filewrite.result b/mysql-test/suite/innodb/r/innodb-alter-filewrite.result new file mode 100644 index 00000000000..444b09ad440 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb-alter-filewrite.result @@ -0,0 +1,30 @@ +CREATE TABLE `test_wo_keys` ( +`f01` int AUTO_INCREMENT, +`f02` bigint, `f03` bigint, `f04` enum('a','b'), +`f05` date, `f06` int, `f07` int, `f08` double, `f09` int, +`f10` bigint, `f11` double, `f12` enum('a','b','c','d','e'), +`f13` int, `f14` int, `f15` varchar(255), `f16` int, `f17` int, `f18` int, +`f19` double, `f20` double, `f21` double, `f22` double, `f23` double, `f24` tinyint, +`f25` double, `f26` double, `f27` double, `f28` double, `f29` int unsigned, +`f30` int unsigned, `f31` bigint, `f32` int unsigned, `f33` bigint, +`f34` int unsigned, `f35` int unsigned, +PRIMARY KEY `f01` (`f01`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +show status like '%merge_buffers%'; +Variable_name Value +Innodb_os_merge_buffers_written 0 +Innodb_os_merge_buffers_read 0 +Innodb_os_merge_buffers_merged 0 +ALTER TABLE test_wo_keys +ADD KEY `f06` (`f06`), ADD KEY `f05` (`f05`), ADD KEY `f04` (`f04`), ADD KEY `f23` (`f23`), +ADD KEY `f10` (`f10`), ADD KEY `f11` (`f11`), ADD KEY `f09` (`f09`), ADD KEY `f22` (`f22`), +ADD KEY `f21` (`f21`), ADD KEY `f07` (`f07`), ADD KEY `f08` (`f08`), ADD KEY `f18` (`f18`), +ADD KEY `f19` (`f19`), ADD KEY `f20` (`f20`), ADD KEY `f29` (`f29`,`f31`,`f33`), +ADD KEY `f35` (`f35`), ADD KEY `f25` (`f25`), ADD KEY `f26` (`f26`), +ADD KEY `f27` (`f27`), ADD KEY `f28` (`f28`); +show status like '%merge_buffers%'; +Variable_name Value +Innodb_os_merge_buffers_written 0 +Innodb_os_merge_buffers_read 0 +Innodb_os_merge_buffers_merged 0 +DROP TABLE test_wo_keys; diff --git a/mysql-test/suite/innodb/r/innodb_monitor.result b/mysql-test/suite/innodb/r/innodb_monitor.result index f8d24f4e6f5..89ce676e38b 100644 --- a/mysql-test/suite/innodb/r/innodb_monitor.result +++ b/mysql-test/suite/innodb/r/innodb_monitor.result @@ -123,6 +123,9 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs disabled os_log_pending_writes disabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled trx_rw_commits disabled trx_ro_commits disabled trx_nl_ro_commits disabled @@ -254,6 +257,9 @@ lock_row_lock_time disabled lock_row_lock_time_max disabled lock_row_lock_waits disabled lock_row_lock_time_avg disabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled innodb_rwlock_s_spin_waits disabled innodb_rwlock_x_spin_waits disabled innodb_rwlock_s_spin_rounds disabled @@ -292,6 +298,9 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs enabled os_log_pending_writes enabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled set global innodb_monitor_enable=""; ERROR 42000: Variable 'innodb_monitor_enable' can't be set to the value of '' set global innodb_monitor_enable="_"; diff --git a/mysql-test/suite/innodb/t/innodb-alter-filewrite.test b/mysql-test/suite/innodb/t/innodb-alter-filewrite.test new file mode 100644 index 00000000000..d0372056937 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-alter-filewrite.test @@ -0,0 +1,32 @@ +--source include/have_innodb.inc + +# +# MDEV-8696: Adding indexes on empty table is slow with large innodb_sort_buffer_size. +# + +CREATE TABLE `test_wo_keys` ( +`f01` int AUTO_INCREMENT, +`f02` bigint, `f03` bigint, `f04` enum('a','b'), +`f05` date, `f06` int, `f07` int, `f08` double, `f09` int, +`f10` bigint, `f11` double, `f12` enum('a','b','c','d','e'), +`f13` int, `f14` int, `f15` varchar(255), `f16` int, `f17` int, `f18` int, +`f19` double, `f20` double, `f21` double, `f22` double, `f23` double, `f24` tinyint, +`f25` double, `f26` double, `f27` double, `f28` double, `f29` int unsigned, +`f30` int unsigned, `f31` bigint, `f32` int unsigned, `f33` bigint, +`f34` int unsigned, `f35` int unsigned, +PRIMARY KEY `f01` (`f01`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +show status like '%merge_buffers%'; + +ALTER TABLE test_wo_keys +ADD KEY `f06` (`f06`), ADD KEY `f05` (`f05`), ADD KEY `f04` (`f04`), ADD KEY `f23` (`f23`), +ADD KEY `f10` (`f10`), ADD KEY `f11` (`f11`), ADD KEY `f09` (`f09`), ADD KEY `f22` (`f22`), +ADD KEY `f21` (`f21`), ADD KEY `f07` (`f07`), ADD KEY `f08` (`f08`), ADD KEY `f18` (`f18`), +ADD KEY `f19` (`f19`), ADD KEY `f20` (`f20`), ADD KEY `f29` (`f29`,`f31`,`f33`), +ADD KEY `f35` (`f35`), ADD KEY `f25` (`f25`), ADD KEY `f26` (`f26`), +ADD KEY `f27` (`f27`), ADD KEY `f28` (`f28`); + +show status like '%merge_buffers%'; + +DROP TABLE test_wo_keys; diff --git a/mysql-test/suite/sys_vars/r/innodb_monitor_disable_basic.result b/mysql-test/suite/sys_vars/r/innodb_monitor_disable_basic.result index 8c0af874228..654b6fc51dd 100644 --- a/mysql-test/suite/sys_vars/r/innodb_monitor_disable_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_monitor_disable_basic.result @@ -123,6 +123,9 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs disabled os_log_pending_writes disabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled trx_rw_commits disabled trx_ro_commits disabled trx_nl_ro_commits disabled @@ -254,6 +257,9 @@ lock_row_lock_time disabled lock_row_lock_time_max disabled lock_row_lock_waits disabled lock_row_lock_time_avg disabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled innodb_rwlock_s_spin_waits disabled innodb_rwlock_x_spin_waits disabled innodb_rwlock_s_spin_rounds disabled @@ -292,6 +298,9 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs enabled os_log_pending_writes enabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled set global innodb_monitor_enable=""; ERROR 42000: Variable 'innodb_monitor_enable' can't be set to the value of '' set global innodb_monitor_enable="_"; diff --git a/mysql-test/suite/sys_vars/r/innodb_monitor_enable_basic.result b/mysql-test/suite/sys_vars/r/innodb_monitor_enable_basic.result index 8c0af874228..654b6fc51dd 100644 --- a/mysql-test/suite/sys_vars/r/innodb_monitor_enable_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_monitor_enable_basic.result @@ -123,6 +123,9 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs disabled os_log_pending_writes disabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled trx_rw_commits disabled trx_ro_commits disabled trx_nl_ro_commits disabled @@ -254,6 +257,9 @@ lock_row_lock_time disabled lock_row_lock_time_max disabled lock_row_lock_waits disabled lock_row_lock_time_avg disabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled innodb_rwlock_s_spin_waits disabled innodb_rwlock_x_spin_waits disabled innodb_rwlock_s_spin_rounds disabled @@ -292,6 +298,9 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs enabled os_log_pending_writes enabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled set global innodb_monitor_enable=""; ERROR 42000: Variable 'innodb_monitor_enable' can't be set to the value of '' set global innodb_monitor_enable="_"; diff --git a/mysql-test/suite/sys_vars/r/innodb_monitor_reset_all_basic.result b/mysql-test/suite/sys_vars/r/innodb_monitor_reset_all_basic.result index 8c0af874228..654b6fc51dd 100644 --- a/mysql-test/suite/sys_vars/r/innodb_monitor_reset_all_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_monitor_reset_all_basic.result @@ -123,6 +123,9 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs disabled os_log_pending_writes disabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled trx_rw_commits disabled trx_ro_commits disabled trx_nl_ro_commits disabled @@ -254,6 +257,9 @@ lock_row_lock_time disabled lock_row_lock_time_max disabled lock_row_lock_waits disabled lock_row_lock_time_avg disabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled innodb_rwlock_s_spin_waits disabled innodb_rwlock_x_spin_waits disabled innodb_rwlock_s_spin_rounds disabled @@ -292,6 +298,9 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs enabled os_log_pending_writes enabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled set global innodb_monitor_enable=""; ERROR 42000: Variable 'innodb_monitor_enable' can't be set to the value of '' set global innodb_monitor_enable="_"; diff --git a/mysql-test/suite/sys_vars/r/innodb_monitor_reset_basic.result b/mysql-test/suite/sys_vars/r/innodb_monitor_reset_basic.result index 8c0af874228..654b6fc51dd 100644 --- a/mysql-test/suite/sys_vars/r/innodb_monitor_reset_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_monitor_reset_basic.result @@ -123,6 +123,9 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs disabled os_log_pending_writes disabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled trx_rw_commits disabled trx_ro_commits disabled trx_nl_ro_commits disabled @@ -254,6 +257,9 @@ lock_row_lock_time disabled lock_row_lock_time_max disabled lock_row_lock_waits disabled lock_row_lock_time_avg disabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled innodb_rwlock_s_spin_waits disabled innodb_rwlock_x_spin_waits disabled innodb_rwlock_s_spin_rounds disabled @@ -292,6 +298,9 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs enabled os_log_pending_writes enabled +os_merge_blocks_written disabled +os_merge_blocks_read disabled +os_merge_blocks_merged disabled set global innodb_monitor_enable=""; ERROR 42000: Variable 'innodb_monitor_enable' can't be set to the value of '' set global innodb_monitor_enable="_"; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 3e7b471a609..926fb0580bb 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4,7 +4,7 @@ Copyright (c) 2000, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2014 SkySQL Ab. All Rights Reserved. +Copyright (c) 2013, 2015, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -644,6 +644,12 @@ static SHOW_VAR innodb_status_variables[]= { (char*) &export_vars.innodb_os_log_pending_writes, SHOW_LONG}, {"os_log_written", (char*) &export_vars.innodb_os_log_written, SHOW_LONGLONG}, + {"os_merge_buffers_written", + (char*) &export_vars.innodb_merge_buffers_written, SHOW_LONGLONG}, + {"os_merge_buffers_read", + (char*) &export_vars.innodb_merge_buffers_read, SHOW_LONGLONG}, + {"os_merge_buffers_merged", + (char*) &export_vars.innodb_merge_buffers_merged, SHOW_LONGLONG}, {"page_size", (char*) &export_vars.innodb_page_size, SHOW_LONG}, {"pages_created", diff --git a/storage/innobase/include/srv0mon.h b/storage/innobase/include/srv0mon.h index 2d90f47eefe..d2b65721e1a 100644 --- a/storage/innobase/include/srv0mon.h +++ b/storage/innobase/include/srv0mon.h @@ -2,6 +2,7 @@ Copyright (c) 2010, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2014, 2015, 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 @@ -255,6 +256,9 @@ enum monitor_id_t { MONITOR_OVLD_OS_LOG_FSYNC, MONITOR_OVLD_OS_LOG_PENDING_FSYNC, MONITOR_OVLD_OS_LOG_PENDING_WRITES, + MONITOR_MERGE_BLOCKS_WRITTEN, + MONITOR_MERGE_BLOCKS_READ, + MONITOR_MERGE_BLOCKS_MERGED, /* Transaction related counters */ MONITOR_MODULE_TRX, diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 63b73a07746..338ad552ab4 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -3,7 +3,7 @@ Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2008, 2009, Google Inc. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved. +Copyright (c) 2013, 2015, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -138,6 +138,15 @@ struct srv_stats_t { /** Number of system rows inserted */ ulint_ctr_64_t n_system_rows_inserted; + + /** Number of merge buffers written */ + ulint_ctr_64_t merge_buffers_written; + + /** Number of merge buffers read */ + ulint_ctr_64_t merge_buffers_read; + + /** Number of merge buffers merged */ + ulint_ctr_64_t merge_buffers_merged; }; extern const char* srv_main_thread_op_info; @@ -875,6 +884,9 @@ struct export_var_t{ ulint innodb_purge_view_trx_id_age; /*!< rw_max_trx_id - purged view's min trx_id */ #endif /* UNIV_DEBUG */ + ib_int64_t innodb_merge_buffers_written; + ib_int64_t innodb_merge_buffers_read; + ib_int64_t innodb_merge_buffers_merged; }; /** Thread slot in the thread table. */ diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 284081d4b0c..75aa423b2ac 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2005, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2014, 2015, 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 @@ -871,6 +872,8 @@ row_merge_read( success = os_file_read_no_error_handling(OS_FILE_FROM_FD(fd), buf, ofs, srv_sort_buf_size); + srv_stats.merge_buffers_read.inc(); + #ifdef POSIX_FADV_DONTNEED /* Each block is read exactly once. Free up the file cache. */ posix_fadvise(fd, ofs, srv_sort_buf_size, POSIX_FADV_DONTNEED); @@ -905,6 +908,7 @@ row_merge_write( DBUG_EXECUTE_IF("row_merge_write_failure", return(FALSE);); ret = os_file_write("(merge)", OS_FILE_FROM_FD(fd), buf, ofs, buf_len); + srv_stats.merge_buffers_written.inc(); #ifdef UNIV_DEBUG if (row_merge_print_block_write) { @@ -1736,7 +1740,7 @@ write_buffers: /* We have enough data tuples to form a block. Sort them and write to disk. */ - if (buf->n_tuples) { + if (UNIV_LIKELY(buf->n_tuples)) { if (dict_index_is_unique(buf->index)) { row_merge_dup_t dup = { buf->index, table, col_map, 0}; @@ -1777,13 +1781,17 @@ write_buffers: dict_index_get_lock(buf->index)); } - row_merge_buf_write(buf, file, block); + /* Do not write empty buffers to temporary file */ + if (buf->n_tuples) { - if (!row_merge_write(file->fd, file->offset++, - block)) { - err = DB_TEMP_FILE_WRITE_FAILURE; - trx->error_key_num = i; - break; + row_merge_buf_write(buf, file, block); + + if (!row_merge_write(file->fd, file->offset++, + block)) { + err = DB_TEMP_FILE_WRITE_FAILURE; + trx->error_key_num = i; + break; + } } UNIV_MEM_INVALID(&block[0], srv_sort_buf_size); @@ -2068,6 +2076,9 @@ done1: mem_heap_free(heap); b2 = row_merge_write_eof(&block[2 * srv_sort_buf_size], b2, of->fd, &of->offset); + + srv_stats.merge_buffers_merged.inc(); + return(b2 ? DB_SUCCESS : DB_CORRUPTION); } @@ -3747,17 +3758,21 @@ wait_again: DEBUG_FTS_SORT_PRINT("FTS_SORT: Complete Insert\n"); #endif } else { - row_merge_dup_t dup = { - sort_idx, table, col_map, 0}; + /* Sorting and inserting is required only if + there really is records */ + if (UNIV_LIKELY(merge_files[i].n_rec)) { + row_merge_dup_t dup = { + sort_idx, table, col_map, 0}; - error = row_merge_sort( - trx, &dup, &merge_files[i], - block, &tmpfd); + error = row_merge_sort( + trx, &dup, &merge_files[i], + block, &tmpfd); - if (error == DB_SUCCESS) { - error = row_merge_insert_index_tuples( - trx->id, sort_idx, old_table, - merge_files[i].fd, block); + if (error == DB_SUCCESS) { + error = row_merge_insert_index_tuples( + trx->id, sort_idx, old_table, + merge_files[i].fd, block); + } } } diff --git a/storage/innobase/srv/srv0mon.cc b/storage/innobase/srv/srv0mon.cc index a0dd32c203f..960c889f871 100644 --- a/storage/innobase/srv/srv0mon.cc +++ b/storage/innobase/srv/srv0mon.cc @@ -2,6 +2,7 @@ Copyright (c) 2010, 2014, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2014, 2015, 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 @@ -674,6 +675,24 @@ static monitor_info_t innodb_counter_info[] = MONITOR_EXISTING | MONITOR_DEFAULT_ON), MONITOR_DEFAULT_START, MONITOR_OVLD_OS_LOG_PENDING_WRITES}, + {"os_merge_blocks_written", "os", + "Number of merge blocks written (innodb_os_merge_blocks_written)", + static_cast( + MONITOR_EXISTING | MONITOR_DEFAULT_ON), + MONITOR_DEFAULT_START, MONITOR_MERGE_BLOCKS_WRITTEN}, + + {"os_merge_blocks_read", "os", + "Number of merge blocks read (innodb_os_merge_blocks_read)", + static_cast( + MONITOR_EXISTING | MONITOR_DEFAULT_ON), + MONITOR_DEFAULT_START, MONITOR_MERGE_BLOCKS_READ}, + + {"os_merge_blocks_merged", "os", + "Number of merge blocks merged (innodb_os_merge_blocks_merged)", + static_cast( + MONITOR_EXISTING | MONITOR_DEFAULT_ON), + MONITOR_DEFAULT_START, MONITOR_MERGE_BLOCKS_MERGED}, + /* ========== Counters for Transaction Module ========== */ {"module_trx", "transaction", "Transaction Manager", MONITOR_MODULE, @@ -1626,6 +1645,21 @@ srv_mon_process_existing_counter( update_min = TRUE; break; + /* innodb_os_merge_blocks_written */ + case MONITOR_MERGE_BLOCKS_WRITTEN: + value = srv_stats.merge_buffers_written; + break; + + /* innodb_os_merge_blocks_read */ + case MONITOR_MERGE_BLOCKS_READ: + value = srv_stats.merge_buffers_read; + break; + + /* innodb_os_merge_blocks_merged */ + case MONITOR_MERGE_BLOCKS_MERGED: + value = srv_stats.merge_buffers_merged; + break; + /* innodb_log_waits */ case MONITOR_OVLD_LOG_WAITS: value = srv_stats.log_waits; diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 89dadf9f08c..b3df528f6ca 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -3,7 +3,7 @@ Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved. +Copyright (c) 2013, 2015, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -1551,6 +1551,10 @@ srv_export_innodb_status(void) } #endif /* UNIV_DEBUG */ + export_vars.innodb_merge_buffers_written = srv_stats.merge_buffers_written; + export_vars.innodb_merge_buffers_read = srv_stats.merge_buffers_read; + export_vars.innodb_merge_buffers_merged = srv_stats.merge_buffers_merged; + mutex_exit(&srv_innodb_monitor_mutex); } diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 4ad637d57d3..c55a260be9a 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -4,7 +4,7 @@ Copyright (c) 2000, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2014 SkySQL Ab. All Rights Reserved. +Copyright (c) 2013, 2015, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -824,6 +824,12 @@ static SHOW_VAR innodb_status_variables[]= { (char*) &export_vars.innodb_os_log_pending_writes, SHOW_LONG}, {"os_log_written", (char*) &export_vars.innodb_os_log_written, SHOW_LONGLONG}, + {"os_merge_buffers_written", + (char*) &export_vars.innodb_merge_buffers_written, SHOW_LONGLONG}, + {"os_merge_buffers_read", + (char*) &export_vars.innodb_merge_buffers_read, SHOW_LONGLONG}, + {"os_merge_buffers_merged", + (char*) &export_vars.innodb_merge_buffers_merged, SHOW_LONGLONG}, {"page_size", (char*) &export_vars.innodb_page_size, SHOW_LONG}, {"pages_created", diff --git a/storage/xtradb/include/srv0mon.h b/storage/xtradb/include/srv0mon.h index 2d90f47eefe..d2b65721e1a 100644 --- a/storage/xtradb/include/srv0mon.h +++ b/storage/xtradb/include/srv0mon.h @@ -2,6 +2,7 @@ Copyright (c) 2010, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2014, 2015, 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 @@ -255,6 +256,9 @@ enum monitor_id_t { MONITOR_OVLD_OS_LOG_FSYNC, MONITOR_OVLD_OS_LOG_PENDING_FSYNC, MONITOR_OVLD_OS_LOG_PENDING_WRITES, + MONITOR_MERGE_BLOCKS_WRITTEN, + MONITOR_MERGE_BLOCKS_READ, + MONITOR_MERGE_BLOCKS_MERGED, /* Transaction related counters */ MONITOR_MODULE_TRX, diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h index 6deb8dc5584..14c9cd4de26 100644 --- a/storage/xtradb/include/srv0srv.h +++ b/storage/xtradb/include/srv0srv.h @@ -3,7 +3,7 @@ Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2008, 2009, Google Inc. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved. +Copyright (c) 2013, 2015, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -145,6 +145,13 @@ struct srv_stats_t { /** Number of lock waits that have been up to max time (i.e.) lock wait timeout */ ulint_ctr_1_t n_lock_max_wait_time; + + /** Number of merge buffers written */ + ulint_ctr_64_t merge_buffers_written; + /** Number of merge buffers read */ + ulint_ctr_64_t merge_buffers_read; + /** Number of merge buffers merged */ + ulint_ctr_64_t merge_buffers_merged; }; extern const char* srv_main_thread_op_info; @@ -1088,6 +1095,9 @@ struct export_var_t{ ulint innodb_purge_view_trx_id_age; /*!< rw_max_trx_id - purged view's min trx_id */ #endif /* UNIV_DEBUG */ + ib_int64_t innodb_merge_buffers_written; + ib_int64_t innodb_merge_buffers_read; + ib_int64_t innodb_merge_buffers_merged; }; /** Thread slot in the thread table. */ diff --git a/storage/xtradb/row/row0merge.cc b/storage/xtradb/row/row0merge.cc index 0a5eb4374f1..3447d15ed1c 100644 --- a/storage/xtradb/row/row0merge.cc +++ b/storage/xtradb/row/row0merge.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2005, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2014, 2015, 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 @@ -873,6 +874,8 @@ row_merge_read( success = os_file_read_no_error_handling(OS_FILE_FROM_FD(fd), buf, ofs, srv_sort_buf_size); + srv_stats.merge_buffers_read.inc(); + #ifdef POSIX_FADV_DONTNEED /* Each block is read exactly once. Free up the file cache. */ posix_fadvise(fd, ofs, srv_sort_buf_size, POSIX_FADV_DONTNEED); @@ -907,6 +910,7 @@ row_merge_write( DBUG_EXECUTE_IF("row_merge_write_failure", return(FALSE);); ret = os_file_write("(merge)", OS_FILE_FROM_FD(fd), buf, ofs, buf_len); + srv_stats.merge_buffers_written.inc(); #ifdef UNIV_DEBUG if (row_merge_print_block_write) { @@ -1744,7 +1748,7 @@ write_buffers: /* We have enough data tuples to form a block. Sort them and write to disk. */ - if (buf->n_tuples) { + if (UNIV_LIKELY(buf->n_tuples)) { if (dict_index_is_unique(buf->index)) { row_merge_dup_t dup = { buf->index, table, col_map, 0}; @@ -1785,13 +1789,17 @@ write_buffers: dict_index_get_lock(buf->index)); } - row_merge_buf_write(buf, file, block); + /* Do not write empty buffers to temporary file */ + if (buf->n_tuples) { - if (!row_merge_write(file->fd, file->offset++, - block)) { - err = DB_TEMP_FILE_WRITE_FAILURE; - trx->error_key_num = i; - break; + row_merge_buf_write(buf, file, block); + + if (!row_merge_write(file->fd, file->offset++, + block)) { + err = DB_TEMP_FILE_WRITE_FAILURE; + trx->error_key_num = i; + break; + } } UNIV_MEM_INVALID(&block[0], srv_sort_buf_size); @@ -2076,6 +2084,9 @@ done1: mem_heap_free(heap); b2 = row_merge_write_eof(&block[2 * srv_sort_buf_size], b2, of->fd, &of->offset); + + srv_stats.merge_buffers_merged.inc(); + return(b2 ? DB_SUCCESS : DB_CORRUPTION); } @@ -3755,17 +3766,21 @@ wait_again: DEBUG_FTS_SORT_PRINT("FTS_SORT: Complete Insert\n"); #endif } else { - row_merge_dup_t dup = { - sort_idx, table, col_map, 0}; + /* Sorting and inserting is required only if + there really is records */ + if (UNIV_LIKELY(merge_files[i].n_rec)) { + row_merge_dup_t dup = { + sort_idx, table, col_map, 0}; - error = row_merge_sort( - trx, &dup, &merge_files[i], - block, &tmpfd); + error = row_merge_sort( + trx, &dup, &merge_files[i], + block, &tmpfd); - if (error == DB_SUCCESS) { - error = row_merge_insert_index_tuples( - trx->id, sort_idx, old_table, - merge_files[i].fd, block); + if (error == DB_SUCCESS) { + error = row_merge_insert_index_tuples( + trx->id, sort_idx, old_table, + merge_files[i].fd, block); + } } } diff --git a/storage/xtradb/srv/srv0mon.cc b/storage/xtradb/srv/srv0mon.cc index a0dd32c203f..960c889f871 100644 --- a/storage/xtradb/srv/srv0mon.cc +++ b/storage/xtradb/srv/srv0mon.cc @@ -2,6 +2,7 @@ Copyright (c) 2010, 2014, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2014, 2015, 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 @@ -674,6 +675,24 @@ static monitor_info_t innodb_counter_info[] = MONITOR_EXISTING | MONITOR_DEFAULT_ON), MONITOR_DEFAULT_START, MONITOR_OVLD_OS_LOG_PENDING_WRITES}, + {"os_merge_blocks_written", "os", + "Number of merge blocks written (innodb_os_merge_blocks_written)", + static_cast( + MONITOR_EXISTING | MONITOR_DEFAULT_ON), + MONITOR_DEFAULT_START, MONITOR_MERGE_BLOCKS_WRITTEN}, + + {"os_merge_blocks_read", "os", + "Number of merge blocks read (innodb_os_merge_blocks_read)", + static_cast( + MONITOR_EXISTING | MONITOR_DEFAULT_ON), + MONITOR_DEFAULT_START, MONITOR_MERGE_BLOCKS_READ}, + + {"os_merge_blocks_merged", "os", + "Number of merge blocks merged (innodb_os_merge_blocks_merged)", + static_cast( + MONITOR_EXISTING | MONITOR_DEFAULT_ON), + MONITOR_DEFAULT_START, MONITOR_MERGE_BLOCKS_MERGED}, + /* ========== Counters for Transaction Module ========== */ {"module_trx", "transaction", "Transaction Manager", MONITOR_MODULE, @@ -1626,6 +1645,21 @@ srv_mon_process_existing_counter( update_min = TRUE; break; + /* innodb_os_merge_blocks_written */ + case MONITOR_MERGE_BLOCKS_WRITTEN: + value = srv_stats.merge_buffers_written; + break; + + /* innodb_os_merge_blocks_read */ + case MONITOR_MERGE_BLOCKS_READ: + value = srv_stats.merge_buffers_read; + break; + + /* innodb_os_merge_blocks_merged */ + case MONITOR_MERGE_BLOCKS_MERGED: + value = srv_stats.merge_buffers_merged; + break; + /* innodb_log_waits */ case MONITOR_OVLD_LOG_WAITS: value = srv_stats.log_waits; diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc index e679e180d45..da293a4dd3f 100644 --- a/storage/xtradb/srv/srv0srv.cc +++ b/storage/xtradb/srv/srv0srv.cc @@ -3,7 +3,7 @@ Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved. +Copyright (c) 2013, 2015, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -1927,6 +1927,10 @@ srv_export_innodb_status(void) } #endif /* UNIV_DEBUG */ + export_vars.innodb_merge_buffers_written = srv_stats.merge_buffers_written; + export_vars.innodb_merge_buffers_read = srv_stats.merge_buffers_read; + export_vars.innodb_merge_buffers_merged = srv_stats.merge_buffers_merged; + mutex_exit(&srv_innodb_monitor_mutex); } From 4834d822efe5a812d251f254387b3f80beb9380d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 28 Oct 2015 08:42:51 +0200 Subject: [PATCH 32/67] MDEV-8932: innodb buffer pool hit rate is less than zero In buffer pool read hit rate calculation can lead rate that is less than zero. --- storage/innobase/buf/buf0buf.cc | 12 ++++++++++-- storage/xtradb/buf/buf0buf.cc | 12 ++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 93d8e70c819..6d8edfca5c0 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -5299,11 +5299,19 @@ buf_print_io_instance( pool_info->pages_written_rate); if (pool_info->n_page_get_delta) { + double hit_rate = ((1000 * pool_info->page_read_delta) + / pool_info->n_page_get_delta); + + if (hit_rate > 1000) { + hit_rate = 1000; + } + + hit_rate = 1000 - hit_rate; + fprintf(file, "Buffer pool hit rate %lu / 1000," " young-making rate %lu / 1000 not %lu / 1000\n", - (ulong) (1000 - (1000 * pool_info->page_read_delta - / pool_info->n_page_get_delta)), + (ulong) hit_rate, (ulong) (1000 * pool_info->young_making_delta / pool_info->n_page_get_delta), (ulong) (1000 * pool_info->not_young_making_delta diff --git a/storage/xtradb/buf/buf0buf.cc b/storage/xtradb/buf/buf0buf.cc index 793456cb7c9..895957dbe10 100644 --- a/storage/xtradb/buf/buf0buf.cc +++ b/storage/xtradb/buf/buf0buf.cc @@ -5524,11 +5524,19 @@ buf_print_io_instance( pool_info->pages_written_rate); if (pool_info->n_page_get_delta) { + double hit_rate = ((1000 * pool_info->page_read_delta) + / pool_info->n_page_get_delta); + + if (hit_rate > 1000) { + hit_rate = 1000; + } + + hit_rate = 1000 - hit_rate; + fprintf(file, "Buffer pool hit rate %lu / 1000," " young-making rate %lu / 1000 not %lu / 1000\n", - (ulong) (1000 - (1000 * pool_info->page_read_delta - / pool_info->n_page_get_delta)), + (ulong) hit_rate, (ulong) (1000 * pool_info->young_making_delta / pool_info->n_page_get_delta), (ulong) (1000 * pool_info->not_young_making_delta From e1ed331ceabbf51b3409529ec78039c42324e1b0 Mon Sep 17 00:00:00 2001 From: Aditya A Date: Tue, 1 Jul 2014 16:52:35 +0530 Subject: [PATCH 33/67] MDEV-8805 - Assertion `!m_ordered_rec_buffer' failed in ha_partition::init_record_priority_queue() Cherry-pick rev.6b0ee0c795499cee7f9deb649fb010801e0be4c2 from mysql-5.6. Bug #18305270 BACKPORT BUG#18694052 FIX FOR ASSERTION `!M_ORDERED_REC_BUFFER' FAILED TO 5.6 PROBLEM ------- Missed to remove record priority queue if init_index failed for a partition which was causing the crash. FIX --- Remove priority queue if init_index fails for partition. --- mysql-test/r/partition_innodb.result | 34 ++++++++++ .../suite/parts/r/partition_debug.result | 16 +++++ mysql-test/suite/parts/t/partition_debug.test | 18 +++++ mysql-test/t/AAA.test | 66 +++++++++++++++++++ mysql-test/t/partition_innodb.test | 42 ++++++++++++ sql/ha_partition.cc | 1 + 6 files changed, 177 insertions(+) create mode 100644 mysql-test/t/AAA.test diff --git a/mysql-test/r/partition_innodb.result b/mysql-test/r/partition_innodb.result index 798e3b9a6bf..f1c3795791a 100644 --- a/mysql-test/r/partition_innodb.result +++ b/mysql-test/r/partition_innodb.result @@ -765,3 +765,37 @@ f1 f2 f3 f4 f5 f6 INSERT INTO t3 SELECT * FROM t2 WHERE f3 = 'm' AND f2 ='c'; DROP TABLE t1,t2,t3; set global default_storage_engine=default; +# +# Bug#13737949: CRASH IN HA_PARTITION::INDEX_INIT +# Bug#18694052: SERVER CRASH IN HA_PARTITION::INIT_RECORD_PRIORITY_QUEUE +# +CREATE TABLE t1 +(a INT, +b INT, +PRIMARY KEY (a)) +ENGINE = InnoDB +PARTITION BY HASH (a) PARTITIONS 3; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +# con1 +ALTER TABLE t1 ADD INDEX idx1 (b); +# con default +SELECT b FROM t1 WHERE b = 0; +ERROR HY000: Table definition has changed, please retry transaction +SELECT b FROM t1 WHERE b = 0; +ERROR HY000: Table definition has changed, please retry transaction +DROP TABLE t1; +# Same test without partitioning +CREATE TABLE t1 +(a INT, +b INT, +PRIMARY KEY (a)) +ENGINE = InnoDB; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +# con1 +ALTER TABLE t1 ADD INDEX idx1 (b); +# con default +SELECT b FROM t1 WHERE b = 0; +ERROR HY000: Table definition has changed, please retry transaction +SELECT b FROM t1 WHERE b = 0; +ERROR HY000: Table definition has changed, please retry transaction +DROP TABLE t1; diff --git a/mysql-test/suite/parts/r/partition_debug.result b/mysql-test/suite/parts/r/partition_debug.result index 3f0f2def790..109072be49c 100644 --- a/mysql-test/suite/parts/r/partition_debug.result +++ b/mysql-test/suite/parts/r/partition_debug.result @@ -1,5 +1,21 @@ DROP TABLE IF EXISTS t1; # +# Bug#13737949: CRASH IN HA_PARTITION::INDEX_INIT +# Bug#18694052: SERVER CRASH IN HA_PARTITION::INIT_RECORD_PRIORITY_QUEUE +# +CREATE TABLE t1 (a INT, b VARCHAR(64), KEY(b,a)) +PARTITION BY HASH (a) PARTITIONS 3; +INSERT INTO t1 VALUES (1, "1"), (2, "2"), (3, "3"), (4, "Four"), (5, "Five"), +(6, "Six"), (7, "Seven"), (8, "Eight"), (9, "Nine"); +SET SESSION debug_dbug="+d,ha_partition_fail_index_init"; +SELECT * FROM t1 WHERE b = "Seven"; +ERROR HY000: Table has no partition for value 0 +SET SESSION debug_dbug="-d,ha_partition_fail_index_init"; +SELECT * FROM t1 WHERE b = "Seven"; +a b +7 Seven +DROP TABLE t1; +# # WL#4445: EXCHANGE PARTITION WITH TABLE # Verify ddl_log in case of crashing. call mtr.add_suppression("Attempting backtrace. You can use the following information to find out"); diff --git a/mysql-test/suite/parts/t/partition_debug.test b/mysql-test/suite/parts/t/partition_debug.test index aa943e5fbe1..11b66e4afd8 100644 --- a/mysql-test/suite/parts/t/partition_debug.test +++ b/mysql-test/suite/parts/t/partition_debug.test @@ -12,6 +12,24 @@ DROP TABLE IF EXISTS t1; --enable_warnings +# Partitioning test that require debug features + +--echo # +--echo # Bug#13737949: CRASH IN HA_PARTITION::INDEX_INIT +--echo # Bug#18694052: SERVER CRASH IN HA_PARTITION::INIT_RECORD_PRIORITY_QUEUE +--echo # +CREATE TABLE t1 (a INT, b VARCHAR(64), KEY(b,a)) + PARTITION BY HASH (a) PARTITIONS 3; + INSERT INTO t1 VALUES (1, "1"), (2, "2"), (3, "3"), (4, "Four"), (5, "Five"), + (6, "Six"), (7, "Seven"), (8, "Eight"), (9, "Nine"); +SET SESSION debug_dbug="+d,ha_partition_fail_index_init"; +--error ER_NO_PARTITION_FOR_GIVEN_VALUE +SELECT * FROM t1 WHERE b = "Seven"; +SET SESSION debug_dbug="-d,ha_partition_fail_index_init"; +SELECT * FROM t1 WHERE b = "Seven"; +DROP TABLE t1; + + --let $DATADIR= `SELECT @@datadir;` --echo # diff --git a/mysql-test/t/AAA.test b/mysql-test/t/AAA.test new file mode 100644 index 00000000000..e9547e84108 --- /dev/null +++ b/mysql-test/t/AAA.test @@ -0,0 +1,66 @@ +#delimiter |; +#create procedure p0(x int) +#while x do +# set x = x-1; +#end while| +#delimiter ;| +#call p0(100000000); +#drop procedure p0; +# +#disable_query_log; +#disable_result_log; +#let $1= 100000000; +#while ($1) +#{ +# SELECT 1; +# dec $1; +#} +#enable_query_log; +#enable_result_log; +#SELECT 'done'; + +--source include/have_innodb.inc +--source include/have_partition.inc + +--enable_connect_log + +SET GLOBAL innodb_lock_wait_timeout = 3; + +CREATE TABLE t1 (pk int auto_increment primary key) ENGINE=InnoDB + PARTITION BY key (pk) partitions 2; + +CREATE TABLE t2 (pk int auto_increment primary key) ENGINE=InnoDB; + +CREATE TABLE t3 (f int) ENGINE=InnoDB; +INSERT INTO t3 VALUES (1),(2); + +--connect (con1,localhost,root,,test) +--connect (con2,localhost,root,,test) +--send ALTER TABLE t1 FORCE; + +--connect (con3,localhost,root,,test) +START TRANSACTION; +INSERT INTO t2 VALUES (1),(2); + +--connection con1 +send UPDATE t3 SET f = 5; + +--connection con3 +SELECT f FROM t3; + +--connection con1 +reap; +--error ER_LOCK_WAIT_TIMEOUT +DELETE FROM t2; + +--connection con3 +--error 0,ER_TABLE_DEF_CHANGED +REPLACE INTO t2 (pk) SELECT NULL FROM t1; + +SELECT * FROM t1; + +disconnect con1; +disconnect con2; +disconnect con3; +connection default; +DROP TABLES t1, t2, t3; diff --git a/mysql-test/t/partition_innodb.test b/mysql-test/t/partition_innodb.test index 2d90764da0d..6845cca10fb 100644 --- a/mysql-test/t/partition_innodb.test +++ b/mysql-test/t/partition_innodb.test @@ -856,3 +856,45 @@ INSERT INTO t3 SELECT * FROM t2 WHERE f3 = 'm' AND f2 ='c'; DROP TABLE t1,t2,t3; set global default_storage_engine=default; + +--echo # +--echo # Bug#13737949: CRASH IN HA_PARTITION::INDEX_INIT +--echo # Bug#18694052: SERVER CRASH IN HA_PARTITION::INIT_RECORD_PRIORITY_QUEUE +--echo # +CREATE TABLE t1 +(a INT, + b INT, + PRIMARY KEY (a)) + ENGINE = InnoDB + PARTITION BY HASH (a) PARTITIONS 3; + START TRANSACTION WITH CONSISTENT SNAPSHOT; + --connect (con1, localhost, root,,) + --echo # con1 + ALTER TABLE t1 ADD INDEX idx1 (b); + --connection default + --echo # con default + --error ER_TABLE_DEF_CHANGED + SELECT b FROM t1 WHERE b = 0; + --error ER_TABLE_DEF_CHANGED + SELECT b FROM t1 WHERE b = 0; + --disconnect con1 + DROP TABLE t1; + +--echo # Same test without partitioning +CREATE TABLE t1 +(a INT, + b INT, + PRIMARY KEY (a)) + ENGINE = InnoDB; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +--echo # con1 +--connect (con1, localhost, root,,) +ALTER TABLE t1 ADD INDEX idx1 (b); +--connection default +--echo # con default +--error ER_TABLE_DEF_CHANGED +SELECT b FROM t1 WHERE b = 0; +--error ER_TABLE_DEF_CHANGED +SELECT b FROM t1 WHERE b = 0; +--disconnect con1 +DROP TABLE t1; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index d8fc647d2a2..e59954e13c2 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -5271,6 +5271,7 @@ err: { (void) m_file[j]->ha_index_end(); } + destroy_record_priority_queue(); } DBUG_RETURN(error); } From ce1b450ab1b75b3c469b8c490e40226973fdad17 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Thu, 22 Oct 2015 13:57:44 +0200 Subject: [PATCH 34/67] MDEV-7930 Assertion `table_share->tmp_table != NO_TMP_TABLE || m_lock_type != 2' failed in handler::ha_index_read_map In optimizing aggregate function do not try to touch tables from outer query. --- mysql-test/r/subselect.result | 24 +++++++++++++++++++ mysql-test/r/subselect_no_exists_to_in.result | 24 +++++++++++++++++++ mysql-test/r/subselect_no_mat.result | 24 +++++++++++++++++++ mysql-test/r/subselect_no_opts.result | 24 +++++++++++++++++++ mysql-test/r/subselect_no_scache.result | 24 +++++++++++++++++++ mysql-test/r/subselect_no_semijoin.result | 24 +++++++++++++++++++ mysql-test/t/subselect.test | 23 ++++++++++++++++++ sql/opt_sum.cc | 6 +++-- 8 files changed, 171 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 87492babe01..f49a9bc4aa0 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -7085,3 +7085,27 @@ sq NULL deallocate prepare stmt; drop table t1,t2,t3,t4; +# +# MDEV-7930: Assertion `table_share->tmp_table != NO_TMP_TABLE || +# m_lock_type != 2' failed in handler::ha_index_read_map +# +CREATE TABLE t1 (f1 INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (f2 INT, KEY(f2)); +INSERT INTO t2 VALUES (3); +CREATE ALGORITHM=MERGE VIEW v2 AS SELECT * FROM t2; +SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; +sq +3 +SELECT * FROM v2 where ( SELECT MIN(v2.f2) FROM t1 ) > 0; +f2 +3 +SELECT count(*) FROM v2 group by ( SELECT MIN(v2.f2) FROM t1 ); +count(*) +1 +delete from t1; +SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; +sq +NULL +drop view v2; +drop table t1,t2; diff --git a/mysql-test/r/subselect_no_exists_to_in.result b/mysql-test/r/subselect_no_exists_to_in.result index e25733cff17..f6434c8fe4c 100644 --- a/mysql-test/r/subselect_no_exists_to_in.result +++ b/mysql-test/r/subselect_no_exists_to_in.result @@ -7085,6 +7085,30 @@ sq NULL deallocate prepare stmt; drop table t1,t2,t3,t4; +# +# MDEV-7930: Assertion `table_share->tmp_table != NO_TMP_TABLE || +# m_lock_type != 2' failed in handler::ha_index_read_map +# +CREATE TABLE t1 (f1 INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (f2 INT, KEY(f2)); +INSERT INTO t2 VALUES (3); +CREATE ALGORITHM=MERGE VIEW v2 AS SELECT * FROM t2; +SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; +sq +3 +SELECT * FROM v2 where ( SELECT MIN(v2.f2) FROM t1 ) > 0; +f2 +3 +SELECT count(*) FROM v2 group by ( SELECT MIN(v2.f2) FROM t1 ); +count(*) +1 +delete from t1; +SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; +sq +NULL +drop view v2; +drop table t1,t2; set optimizer_switch=default; select @@optimizer_switch like '%exists_to_in=off%'; @@optimizer_switch like '%exists_to_in=off%' diff --git a/mysql-test/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result index 967a319df9b..49ad0ed4037 100644 --- a/mysql-test/r/subselect_no_mat.result +++ b/mysql-test/r/subselect_no_mat.result @@ -7078,6 +7078,30 @@ sq NULL deallocate prepare stmt; drop table t1,t2,t3,t4; +# +# MDEV-7930: Assertion `table_share->tmp_table != NO_TMP_TABLE || +# m_lock_type != 2' failed in handler::ha_index_read_map +# +CREATE TABLE t1 (f1 INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (f2 INT, KEY(f2)); +INSERT INTO t2 VALUES (3); +CREATE ALGORITHM=MERGE VIEW v2 AS SELECT * FROM t2; +SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; +sq +3 +SELECT * FROM v2 where ( SELECT MIN(v2.f2) FROM t1 ) > 0; +f2 +3 +SELECT count(*) FROM v2 group by ( SELECT MIN(v2.f2) FROM t1 ); +count(*) +1 +delete from t1; +SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; +sq +NULL +drop view v2; +drop table t1,t2; set optimizer_switch=default; select @@optimizer_switch like '%materialization=on%'; @@optimizer_switch like '%materialization=on%' diff --git a/mysql-test/r/subselect_no_opts.result b/mysql-test/r/subselect_no_opts.result index 754a1521bd9..2122747d262 100644 --- a/mysql-test/r/subselect_no_opts.result +++ b/mysql-test/r/subselect_no_opts.result @@ -7076,4 +7076,28 @@ sq NULL deallocate prepare stmt; drop table t1,t2,t3,t4; +# +# MDEV-7930: Assertion `table_share->tmp_table != NO_TMP_TABLE || +# m_lock_type != 2' failed in handler::ha_index_read_map +# +CREATE TABLE t1 (f1 INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (f2 INT, KEY(f2)); +INSERT INTO t2 VALUES (3); +CREATE ALGORITHM=MERGE VIEW v2 AS SELECT * FROM t2; +SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; +sq +3 +SELECT * FROM v2 where ( SELECT MIN(v2.f2) FROM t1 ) > 0; +f2 +3 +SELECT count(*) FROM v2 group by ( SELECT MIN(v2.f2) FROM t1 ); +count(*) +1 +delete from t1; +SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; +sq +NULL +drop view v2; +drop table t1,t2; set @optimizer_switch_for_subselect_test=null; diff --git a/mysql-test/r/subselect_no_scache.result b/mysql-test/r/subselect_no_scache.result index f5c0e9ddf79..a1c468ba334 100644 --- a/mysql-test/r/subselect_no_scache.result +++ b/mysql-test/r/subselect_no_scache.result @@ -7091,6 +7091,30 @@ sq NULL deallocate prepare stmt; drop table t1,t2,t3,t4; +# +# MDEV-7930: Assertion `table_share->tmp_table != NO_TMP_TABLE || +# m_lock_type != 2' failed in handler::ha_index_read_map +# +CREATE TABLE t1 (f1 INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (f2 INT, KEY(f2)); +INSERT INTO t2 VALUES (3); +CREATE ALGORITHM=MERGE VIEW v2 AS SELECT * FROM t2; +SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; +sq +3 +SELECT * FROM v2 where ( SELECT MIN(v2.f2) FROM t1 ) > 0; +f2 +3 +SELECT count(*) FROM v2 group by ( SELECT MIN(v2.f2) FROM t1 ); +count(*) +1 +delete from t1; +SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; +sq +NULL +drop view v2; +drop table t1,t2; set optimizer_switch=default; select @@optimizer_switch like '%subquery_cache=on%'; @@optimizer_switch like '%subquery_cache=on%' diff --git a/mysql-test/r/subselect_no_semijoin.result b/mysql-test/r/subselect_no_semijoin.result index b16c067ebc8..168908aa356 100644 --- a/mysql-test/r/subselect_no_semijoin.result +++ b/mysql-test/r/subselect_no_semijoin.result @@ -7076,5 +7076,29 @@ sq NULL deallocate prepare stmt; drop table t1,t2,t3,t4; +# +# MDEV-7930: Assertion `table_share->tmp_table != NO_TMP_TABLE || +# m_lock_type != 2' failed in handler::ha_index_read_map +# +CREATE TABLE t1 (f1 INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (f2 INT, KEY(f2)); +INSERT INTO t2 VALUES (3); +CREATE ALGORITHM=MERGE VIEW v2 AS SELECT * FROM t2; +SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; +sq +3 +SELECT * FROM v2 where ( SELECT MIN(v2.f2) FROM t1 ) > 0; +f2 +3 +SELECT count(*) FROM v2 group by ( SELECT MIN(v2.f2) FROM t1 ); +count(*) +1 +delete from t1; +SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; +sq +NULL +drop view v2; +drop table t1,t2; set @optimizer_switch_for_subselect_test=null; set @join_cache_level_for_subselect_test=NULL; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 67eac0d228c..d6a7300b03a 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -5964,3 +5964,26 @@ EXECUTE stmt; deallocate prepare stmt; drop table t1,t2,t3,t4; + +--echo # +--echo # MDEV-7930: Assertion `table_share->tmp_table != NO_TMP_TABLE || +--echo # m_lock_type != 2' failed in handler::ha_index_read_map +--echo # + +CREATE TABLE t1 (f1 INT); +INSERT INTO t1 VALUES (1),(2); + +CREATE TABLE t2 (f2 INT, KEY(f2)); +INSERT INTO t2 VALUES (3); + +CREATE ALGORITHM=MERGE VIEW v2 AS SELECT * FROM t2; + +SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; +SELECT * FROM v2 where ( SELECT MIN(v2.f2) FROM t1 ) > 0; +SELECT count(*) FROM v2 group by ( SELECT MIN(v2.f2) FROM t1 ); + +delete from t1; +SELECT ( SELECT MIN(v2.f2) FROM t1 ) AS sq FROM v2 GROUP BY sq; + +drop view v2; +drop table t1,t2; diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index fc3ce09dd8e..1ff1f4a6449 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -341,7 +341,8 @@ int opt_sum_query(THD *thd, there are no outer joins. */ if (!conds && !((Item_sum_count*) item)->get_arg(0)->maybe_null && - !outer_tables && maybe_exact_count) + !outer_tables && maybe_exact_count && + ((item->used_tables() & OUTER_REF_TABLE_BIT) == 0)) { if (!is_exact_count) { @@ -369,7 +370,8 @@ int opt_sum_query(THD *thd, indexes to find the key. */ Item *expr=item_sum->get_arg(0); - if (expr->real_item()->type() == Item::FIELD_ITEM) + if (((expr->used_tables() & OUTER_REF_TABLE_BIT) == 0) && + expr->real_item()->type() == Item::FIELD_ITEM) { uchar key_buff[MAX_KEY_LENGTH]; TABLE_REF ref; From ac67f9a42ac6b52ea1673fd5bf40e2563b6c4004 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Wed, 28 Oct 2015 12:53:23 +0400 Subject: [PATCH 35/67] Removed mistakenly committed test file. --- mysql-test/t/AAA.test | 66 ------------------------------------------- 1 file changed, 66 deletions(-) delete mode 100644 mysql-test/t/AAA.test diff --git a/mysql-test/t/AAA.test b/mysql-test/t/AAA.test deleted file mode 100644 index e9547e84108..00000000000 --- a/mysql-test/t/AAA.test +++ /dev/null @@ -1,66 +0,0 @@ -#delimiter |; -#create procedure p0(x int) -#while x do -# set x = x-1; -#end while| -#delimiter ;| -#call p0(100000000); -#drop procedure p0; -# -#disable_query_log; -#disable_result_log; -#let $1= 100000000; -#while ($1) -#{ -# SELECT 1; -# dec $1; -#} -#enable_query_log; -#enable_result_log; -#SELECT 'done'; - ---source include/have_innodb.inc ---source include/have_partition.inc - ---enable_connect_log - -SET GLOBAL innodb_lock_wait_timeout = 3; - -CREATE TABLE t1 (pk int auto_increment primary key) ENGINE=InnoDB - PARTITION BY key (pk) partitions 2; - -CREATE TABLE t2 (pk int auto_increment primary key) ENGINE=InnoDB; - -CREATE TABLE t3 (f int) ENGINE=InnoDB; -INSERT INTO t3 VALUES (1),(2); - ---connect (con1,localhost,root,,test) ---connect (con2,localhost,root,,test) ---send ALTER TABLE t1 FORCE; - ---connect (con3,localhost,root,,test) -START TRANSACTION; -INSERT INTO t2 VALUES (1),(2); - ---connection con1 -send UPDATE t3 SET f = 5; - ---connection con3 -SELECT f FROM t3; - ---connection con1 -reap; ---error ER_LOCK_WAIT_TIMEOUT -DELETE FROM t2; - ---connection con3 ---error 0,ER_TABLE_DEF_CHANGED -REPLACE INTO t2 (pk) SELECT NULL FROM t1; - -SELECT * FROM t1; - -disconnect con1; -disconnect con2; -disconnect con3; -connection default; -DROP TABLES t1, t2, t3; From b0e3f484f76bfcd26f8da919d621f56972d21aa7 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Thu, 22 Oct 2015 16:08:45 +0200 Subject: [PATCH 36/67] MDEV-8756 MariaDB 10.0.21 crashes during PREPARE Non-select-like queries has no correct JOIN structure connected to top-most SELECT_LEX (and should not). --- mysql-test/r/ps.result | 21 +++++++++++++++++++++ mysql-test/t/ps.test | 22 ++++++++++++++++++++++ sql/item.cc | 20 ++++++++++++++++++-- 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 31fcea528aa..8d073f8da1e 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -4052,3 +4052,24 @@ SELECT 1 FROM t1 GROUP BY 0 OR 18446744073709551615+1; ERROR 22003: BIGINT UNSIGNED value is out of range in '(18446744073709551615 + 1)' drop table t1; # End of 5.3 tests +# +# MDEV-8756: MariaDB 10.0.21 crashes during PREPARE +# +CREATE TABLE t1 ( id INT(10), value INT(10) ); +CREATE TABLE t2 ( id INT(10) ); +SET @save_sql_mode= @@sql_mode; +SET SESSION sql_mode = 'ONLY_FULL_GROUP_BY'; +PREPARE stmt FROM 'UPDATE t1 t1 SET value = (SELECT 1 FROM t2 WHERE id = t1.id)'; +execute stmt; +insert into t1 values (1,10),(2,10),(3,10); +insert into t2 values (1),(2); +execute stmt; +select * from t1; +id value +1 1 +2 1 +3 NULL +deallocate prepare stmt; +SET SESSION sql_mode = @save_sql_mode; +DROP TABLE t1,t2; +# End of 10.0 tests diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 0233b2e428b..c45b27281a7 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -3633,3 +3633,25 @@ SELECT 1 FROM t1 GROUP BY 0 OR 18446744073709551615+1; drop table t1; --echo # End of 5.3 tests + +--echo # +--echo # MDEV-8756: MariaDB 10.0.21 crashes during PREPARE +--echo # + +CREATE TABLE t1 ( id INT(10), value INT(10) ); +CREATE TABLE t2 ( id INT(10) ); +SET @save_sql_mode= @@sql_mode; +SET SESSION sql_mode = 'ONLY_FULL_GROUP_BY'; + +PREPARE stmt FROM 'UPDATE t1 t1 SET value = (SELECT 1 FROM t2 WHERE id = t1.id)'; +execute stmt; +insert into t1 values (1,10),(2,10),(3,10); +insert into t2 values (1),(2); +execute stmt; +select * from t1; +deallocate prepare stmt; +SET SESSION sql_mode = @save_sql_mode; +DROP TABLE t1,t2; + + +--echo # End of 10.0 tests diff --git a/sql/item.cc b/sql/item.cc index 90a8777d8f7..543ea4f0ffb 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4834,8 +4834,24 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) As this is an outer field it should be added to the list of non aggregated fields of the outer select. */ - marker= select->cur_pos_in_select_list; - select->join->non_agg_fields.push_back(this); + if (select->join) + { + marker= select->cur_pos_in_select_list; + select->join->non_agg_fields.push_back(this); + } + else + { + /* + join is absent if it is upper SELECT_LEX of non-select + command + */ + DBUG_ASSERT(select->master_unit()->outer_select() == NULL && + (thd->lex->sql_command != SQLCOM_SELECT && + thd->lex->sql_command != SQLCOM_UPDATE_MULTI && + thd->lex->sql_command != SQLCOM_DELETE_MULTI && + thd->lex->sql_command != SQLCOM_INSERT_SELECT && + thd->lex->sql_command != SQLCOM_REPLACE_SELECT)); + } } if (*from_field != view_ref_found) { From d88aaaa841aefabce770ad73373363275f606d22 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 28 Oct 2015 08:34:08 +0100 Subject: [PATCH 37/67] MDEV-8525 mariadb 10.0.20 crashing when data is read by Kodi media center (http://kodi.tv). Item_direct_view_ref maintains its own item_const() method so should use it when asked of temporary table field to be in sync with it. --- mysql-test/r/view.result | 102 +++++++++++++++++++++++++++++++++++ mysql-test/t/view.test | 113 +++++++++++++++++++++++++++++++++++++++ sql/item.h | 2 + 3 files changed, 217 insertions(+) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 80e90f86826..f697f63ca76 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -5597,6 +5597,108 @@ count(v3.i) 0 drop table t1, t2; drop view v3; +# +# MDEV-8525: mariadb 10.0.20 crashing when data is read by Kodi +# media center (http://kodi.tv). +# +CREATE TABLE `t1` ( +`idSong` int(11) NOT NULL AUTO_INCREMENT, +`idAlbum` int(11) DEFAULT NULL, +`idPath` int(11) DEFAULT NULL, +`strArtists` text, +`strGenres` text, +`strTitle` varchar(512) DEFAULT NULL, +`iTrack` int(11) DEFAULT NULL, +`iDuration` int(11) DEFAULT NULL, +`iYear` int(11) DEFAULT NULL, +`dwFileNameCRC` text, +`strFileName` text, +`strMusicBrainzTrackID` text, +`iTimesPlayed` int(11) DEFAULT NULL, +`iStartOffset` int(11) DEFAULT NULL, +`iEndOffset` int(11) DEFAULT NULL, +`idThumb` int(11) DEFAULT NULL, +`lastplayed` varchar(20) DEFAULT NULL, +`rating` char(1) DEFAULT '0', +`comment` text, +`mood` text, +PRIMARY KEY (`idSong`), +UNIQUE KEY `idxSong7` (`idAlbum`,`strMusicBrainzTrackID`(36)), +KEY `idxSong` (`strTitle`(255)), +KEY `idxSong1` (`iTimesPlayed`), +KEY `idxSong2` (`lastplayed`), +KEY `idxSong3` (`idAlbum`), +KEY `idxSong6` (`idPath`,`strFileName`(255)) +) DEFAULT CHARSET=utf8; +INSERT INTO `t1` VALUES (1,1,1,'strArtists1','strGenres1','strTitle1',1,100,2000,NULL,'strFileName1','strMusicBrainzTrackID1',0,0,0,NULL,NULL,'0','',''),(2,2,2,'strArtists2','strGenres2','strTitle2',2,200,2001,NULL,'strFileName2','strMusicBrainzTrackID2',0,0,0,NULL,NULL,'0','',''); +CREATE TABLE `t2` ( +`idAlbum` int(11) NOT NULL AUTO_INCREMENT, +`strAlbum` varchar(256) DEFAULT NULL, +`strMusicBrainzAlbumID` text, +`strArtists` text, +`strGenres` text, +`iYear` int(11) DEFAULT NULL, +`idThumb` int(11) DEFAULT NULL, +`bCompilation` int(11) NOT NULL DEFAULT '0', +`strMoods` text, +`strStyles` text, +`strThemes` text, +`strReview` text, +`strImage` text, +`strLabel` text, +`strType` text, +`iRating` int(11) DEFAULT NULL, +`lastScraped` varchar(20) DEFAULT NULL, +`dateAdded` varchar(20) DEFAULT NULL, +`strReleaseType` text, +PRIMARY KEY (`idAlbum`), +UNIQUE KEY `idxAlbum_2` (`strMusicBrainzAlbumID`(36)), +KEY `idxAlbum` (`strAlbum`(255)), +KEY `idxAlbum_1` (`bCompilation`) +) DEFAULT CHARSET=utf8; +INSERT INTO `t2` VALUES (1,'strAlbum1','strMusicBrainzAlbumID1','strArtists1','strGenres1',2000,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'album'); +CREATE TABLE `t3` ( +`idArtist` int(11) DEFAULT NULL, +`idAlbum` int(11) DEFAULT NULL, +`strJoinPhrase` text, +`boolFeatured` int(11) DEFAULT NULL, +`iOrder` int(11) DEFAULT NULL, +`strArtist` text, +UNIQUE KEY `idxAlbumArtist_1` (`idAlbum`,`idArtist`), +UNIQUE KEY `idxAlbumArtist_2` (`idArtist`,`idAlbum`), +KEY `idxAlbumArtist_3` (`boolFeatured`) +) DEFAULT CHARSET=utf8; +INSERT INTO `t3` VALUES (1,1,'',0,0,'strArtist1'); +CREATE TABLE `t4` ( +`idArtist` int(11) NOT NULL AUTO_INCREMENT, +`strArtist` varchar(256) DEFAULT NULL, +`strMusicBrainzArtistID` text, +`strBorn` text, +`strFormed` text, +`strGenres` text, +`strMoods` text, +`strStyles` text, +`strInstruments` text, +`strBiography` text, +`strDied` text, +`strDisbanded` text, +`strYearsActive` text, +`strImage` text, +`strFanart` text, +`lastScraped` varchar(20) DEFAULT NULL, +`dateAdded` varchar(20) DEFAULT NULL, +PRIMARY KEY (`idArtist`), +UNIQUE KEY `idxArtist1` (`strMusicBrainzArtistID`(36)), +KEY `idxArtist` (`strArtist`(255)) +) DEFAULT CHARSET=utf8; +INSERT INTO `t4` VALUES (1,'strArtist1','strMusicBrainzArtistID',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); +CREATE VIEW `v1` AS select `t2`.`idAlbum` AS `idAlbum`,`t2`.`strAlbum` AS `strAlbum`,`t2`.`strMusicBrainzAlbumID` AS `strMusicBrainzAlbumID`,`t2`.`strArtists` AS `strArtists`,`t2`.`strGenres` AS `strGenres`,`t2`.`iYear` AS `iYear`,`t2`.`strMoods` AS `strMoods`,`t2`.`strStyles` AS `strStyles`,`t2`.`strThemes` AS `strThemes`,`t2`.`strReview` AS `strReview`,`t2`.`strLabel` AS `strLabel`,`t2`.`strType` AS `strType`,`t2`.`strImage` AS `strImage`,`t2`.`iRating` AS `iRating`,`t2`.`bCompilation` AS `bCompilation`,(select min(`t1`.`iTimesPlayed`) from `t1` where (`t1`.`idAlbum` = `t2`.`idAlbum`)) AS `iTimesPlayed`,`t2`.`strReleaseType` AS `strReleaseType` from `t2`; +CREATE VIEW `v2` AS select `t3`.`idAlbum` AS `idAlbum`,`t3`.`idArtist` AS `idArtist`,`t4`.`strArtist` AS `strArtist`,`t4`.`strMusicBrainzArtistID` AS `strMusicBrainzArtistID`,`t3`.`boolFeatured` AS `boolFeatured`,`t3`.`strJoinPhrase` AS `strJoinPhrase`,`t3`.`iOrder` AS `iOrder` from (`t3` join `t4` on((`t3`.`idArtist` = `t4`.`idArtist`))); +SELECT v1.*,v2.* FROM v1 LEFT JOIN v2 ON v1.idAlbum = v2.idAlbum WHERE v1.idAlbum = 1 ORDER BY v2.iOrder; +idAlbum strAlbum strMusicBrainzAlbumID strArtists strGenres iYear strMoods strStyles strThemes strReview strLabel strType strImage iRating bCompilation iTimesPlayed strReleaseType idAlbum idArtist strArtist strMusicBrainzArtistID boolFeatured strJoinPhrase iOrder +1 strAlbum1 strMusicBrainzAlbumID1 strArtists1 strGenres1 2000 NULL NULL NULL NULL NULL NULL NULL NULL 0 0 album 1 1 strArtist1 strMusicBrainzArtistID 0 0 +drop view v1,v2; +drop table t1,t2,t3,t4; # ----------------------------------------------------------------- # -- End of 10.0 tests. # ----------------------------------------------------------------- diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index cf406db6cd8..773df49de6f 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -5489,6 +5489,119 @@ execute stmt; drop table t1, t2; drop view v3; +--echo # +--echo # MDEV-8525: mariadb 10.0.20 crashing when data is read by Kodi +--echo # media center (http://kodi.tv). +--echo # + +CREATE TABLE `t1` ( + `idSong` int(11) NOT NULL AUTO_INCREMENT, + `idAlbum` int(11) DEFAULT NULL, + `idPath` int(11) DEFAULT NULL, + `strArtists` text, + `strGenres` text, + `strTitle` varchar(512) DEFAULT NULL, + `iTrack` int(11) DEFAULT NULL, + `iDuration` int(11) DEFAULT NULL, + `iYear` int(11) DEFAULT NULL, + `dwFileNameCRC` text, + `strFileName` text, + `strMusicBrainzTrackID` text, + `iTimesPlayed` int(11) DEFAULT NULL, + `iStartOffset` int(11) DEFAULT NULL, + `iEndOffset` int(11) DEFAULT NULL, + `idThumb` int(11) DEFAULT NULL, + `lastplayed` varchar(20) DEFAULT NULL, + `rating` char(1) DEFAULT '0', + `comment` text, + `mood` text, + PRIMARY KEY (`idSong`), + UNIQUE KEY `idxSong7` (`idAlbum`,`strMusicBrainzTrackID`(36)), + KEY `idxSong` (`strTitle`(255)), + KEY `idxSong1` (`iTimesPlayed`), + KEY `idxSong2` (`lastplayed`), + KEY `idxSong3` (`idAlbum`), + KEY `idxSong6` (`idPath`,`strFileName`(255)) +) DEFAULT CHARSET=utf8; + +INSERT INTO `t1` VALUES (1,1,1,'strArtists1','strGenres1','strTitle1',1,100,2000,NULL,'strFileName1','strMusicBrainzTrackID1',0,0,0,NULL,NULL,'0','',''),(2,2,2,'strArtists2','strGenres2','strTitle2',2,200,2001,NULL,'strFileName2','strMusicBrainzTrackID2',0,0,0,NULL,NULL,'0','',''); + +CREATE TABLE `t2` ( + `idAlbum` int(11) NOT NULL AUTO_INCREMENT, + `strAlbum` varchar(256) DEFAULT NULL, + `strMusicBrainzAlbumID` text, + `strArtists` text, + `strGenres` text, + `iYear` int(11) DEFAULT NULL, + `idThumb` int(11) DEFAULT NULL, + `bCompilation` int(11) NOT NULL DEFAULT '0', + `strMoods` text, + `strStyles` text, + `strThemes` text, + `strReview` text, + `strImage` text, + `strLabel` text, + `strType` text, + `iRating` int(11) DEFAULT NULL, + `lastScraped` varchar(20) DEFAULT NULL, + `dateAdded` varchar(20) DEFAULT NULL, + `strReleaseType` text, + PRIMARY KEY (`idAlbum`), + UNIQUE KEY `idxAlbum_2` (`strMusicBrainzAlbumID`(36)), + KEY `idxAlbum` (`strAlbum`(255)), + KEY `idxAlbum_1` (`bCompilation`) +) DEFAULT CHARSET=utf8; + +INSERT INTO `t2` VALUES (1,'strAlbum1','strMusicBrainzAlbumID1','strArtists1','strGenres1',2000,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'album'); + +CREATE TABLE `t3` ( + `idArtist` int(11) DEFAULT NULL, + `idAlbum` int(11) DEFAULT NULL, + `strJoinPhrase` text, + `boolFeatured` int(11) DEFAULT NULL, + `iOrder` int(11) DEFAULT NULL, + `strArtist` text, + UNIQUE KEY `idxAlbumArtist_1` (`idAlbum`,`idArtist`), + UNIQUE KEY `idxAlbumArtist_2` (`idArtist`,`idAlbum`), + KEY `idxAlbumArtist_3` (`boolFeatured`) +) DEFAULT CHARSET=utf8; + +INSERT INTO `t3` VALUES (1,1,'',0,0,'strArtist1'); + +CREATE TABLE `t4` ( + `idArtist` int(11) NOT NULL AUTO_INCREMENT, + `strArtist` varchar(256) DEFAULT NULL, + `strMusicBrainzArtistID` text, + `strBorn` text, + `strFormed` text, + `strGenres` text, + `strMoods` text, + `strStyles` text, + `strInstruments` text, + `strBiography` text, + `strDied` text, + `strDisbanded` text, + `strYearsActive` text, + `strImage` text, + `strFanart` text, + `lastScraped` varchar(20) DEFAULT NULL, + `dateAdded` varchar(20) DEFAULT NULL, + PRIMARY KEY (`idArtist`), + UNIQUE KEY `idxArtist1` (`strMusicBrainzArtistID`(36)), + KEY `idxArtist` (`strArtist`(255)) +) DEFAULT CHARSET=utf8; + +INSERT INTO `t4` VALUES (1,'strArtist1','strMusicBrainzArtistID',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); + +CREATE VIEW `v1` AS select `t2`.`idAlbum` AS `idAlbum`,`t2`.`strAlbum` AS `strAlbum`,`t2`.`strMusicBrainzAlbumID` AS `strMusicBrainzAlbumID`,`t2`.`strArtists` AS `strArtists`,`t2`.`strGenres` AS `strGenres`,`t2`.`iYear` AS `iYear`,`t2`.`strMoods` AS `strMoods`,`t2`.`strStyles` AS `strStyles`,`t2`.`strThemes` AS `strThemes`,`t2`.`strReview` AS `strReview`,`t2`.`strLabel` AS `strLabel`,`t2`.`strType` AS `strType`,`t2`.`strImage` AS `strImage`,`t2`.`iRating` AS `iRating`,`t2`.`bCompilation` AS `bCompilation`,(select min(`t1`.`iTimesPlayed`) from `t1` where (`t1`.`idAlbum` = `t2`.`idAlbum`)) AS `iTimesPlayed`,`t2`.`strReleaseType` AS `strReleaseType` from `t2`; + +CREATE VIEW `v2` AS select `t3`.`idAlbum` AS `idAlbum`,`t3`.`idArtist` AS `idArtist`,`t4`.`strArtist` AS `strArtist`,`t4`.`strMusicBrainzArtistID` AS `strMusicBrainzArtistID`,`t3`.`boolFeatured` AS `boolFeatured`,`t3`.`strJoinPhrase` AS `strJoinPhrase`,`t3`.`iOrder` AS `iOrder` from (`t3` join `t4` on((`t3`.`idArtist` = `t4`.`idArtist`))); + +SELECT v1.*,v2.* FROM v1 LEFT JOIN v2 ON v1.idAlbum = v2.idAlbum WHERE v1.idAlbum = 1 ORDER BY v2.iOrder; + +drop view v1,v2; +drop table t1,t2,t3,t4; + --echo # ----------------------------------------------------------------- --echo # -- End of 10.0 tests. --echo # ----------------------------------------------------------------- diff --git a/sql/item.h b/sql/item.h index ec952f3f5a6..5b7c0e815b4 100644 --- a/sql/item.h +++ b/sql/item.h @@ -3770,6 +3770,8 @@ public: bool eq(const Item *item, bool binary_cmp) const; Item *get_tmp_table_item(THD *thd) { + if (const_item()) + return copy_or_same(thd); Item *item= Item_ref::get_tmp_table_item(thd); item->name= name; return item; From d775ecdd010daad4dc6147fba58acd006bf2c60c Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 28 Oct 2015 08:11:54 +0100 Subject: [PATCH 38/67] MDEV-8543 mysql.server script not correctly handle --pid-file. --- support-files/mysql.server.sh | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index e23b8373ec4..be913f7e10e 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -114,12 +114,6 @@ mode=$1 # start or stop [ $# -ge 1 ] && shift - -other_args="$*" # uncommon, but needed when called from an RPM upgrade action - # Expected: "--skip-networking --skip-grant-tables" - # They are not checked here, intentionally, as it is the resposibility - # of the "spec" file author to give correct arguments only. - case `echo "testing\c"`,`echo -n testing` in *c*,-n*) echo_n= echo_c= ;; *c*,*) echo_n=-n echo_c= ;; @@ -211,6 +205,7 @@ else fi parse_server_arguments `$print_defaults $extra_args mysqld server mysql_server mysql.server` +parse_server_arguments "$@" # wait for the pid file to disappear wait_for_gone () { @@ -308,7 +303,7 @@ case "$mode" in then # Give extra arguments to mysqld with the my.cnf file. This script # may be overwritten at next upgrade. - $bindir/mysqld_safe --datadir="$datadir" --pid-file="$mysqld_pid_file_path" $other_args >/dev/null 2>&1 & + $bindir/mysqld_safe --datadir="$datadir" --pid-file="$mysqld_pid_file_path" "$@" >/dev/null 2>&1 & wait_for_ready; return_value=$? # Make lock for RedHat / SuSE @@ -356,8 +351,8 @@ case "$mode" in 'restart') # Stop the service and regardless of whether it was # running or not, start it again. - if $0 stop $other_args; then - $0 start $other_args + if $0 stop "$@"; then + $0 start "$@" else log_failure_msg "Failed to stop running server, so refusing to try to start." exit 1 From 56f04e0dfd0835b207a86729d2f73a8502f71bb0 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 28 Oct 2015 21:32:07 +0100 Subject: [PATCH 39/67] MDEV-9014 SHOW TRIGGERS not case sensitive use table_alias_charset for comparing table names, not files_charset_info --- mysql-test/r/lowercase_fs_off.result | 5 +++++ mysql-test/t/lowercase_fs_off.test | 8 ++++++++ sql/handler.cc | 2 +- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/lowercase_fs_off.result b/mysql-test/r/lowercase_fs_off.result index 9b819cf3843..d7e1b8c9e5b 100644 --- a/mysql-test/r/lowercase_fs_off.result +++ b/mysql-test/r/lowercase_fs_off.result @@ -63,3 +63,8 @@ CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW SET new.a= 1; RENAME TABLE t1 TO T1; ALTER TABLE T1 RENAME t1; DROP TABLE t1; +create table t1 (a int); +create trigger t1_bi before insert on t1 for each row set new.a= 1; +show triggers like '%T1%'; +Trigger Event Table Statement Timing Created sql_mode Definer character_set_client collation_connection Database Collation +drop table t1; diff --git a/mysql-test/t/lowercase_fs_off.test b/mysql-test/t/lowercase_fs_off.test index 1be0351f9bc..01989ef5367 100644 --- a/mysql-test/t/lowercase_fs_off.test +++ b/mysql-test/t/lowercase_fs_off.test @@ -102,3 +102,11 @@ CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW SET new.a= 1; RENAME TABLE t1 TO T1; ALTER TABLE T1 RENAME t1; DROP TABLE t1; + +# +# MDEV-9014 SHOW TRIGGERS not case sensitive +# +create table t1 (a int); +create trigger t1_bi before insert on t1 for each row set new.a= 1; +show triggers like '%T1%'; +drop table t1; diff --git a/sql/handler.cc b/sql/handler.cc index 868a1475a7f..4294a1aaf72 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -5116,7 +5116,7 @@ bool Discovered_table_list::add_table(const char *tname, size_t tlen) custom discover_table_names() method, that calls add_table() directly). Note: avoid comparing the same name twice (here and in add_file). */ - if (wild && my_wildcmp(files_charset_info, tname, tname + tlen, wild, wend, + if (wild && my_wildcmp(table_alias_charset, tname, tname + tlen, wild, wend, wild_prefix, wild_one, wild_many)) return 0; From 59dd58b17eb79bd2daa0c72a86cd4b3b14bae4cc Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 30 Oct 2015 10:10:43 +0400 Subject: [PATCH 40/67] MDEV-8692 prefschema test failures on ARM (on Debian build system) A few tests assumes that the CYCLE timer is always available, which is not true on some platforms (e.g. ARM). Fixing the tests not to reply on the CYCLE availability. --- .../perfschema/include/have_timer_cycle.inc | 4 +++ .../suite/perfschema/r/privilege.result | 5 ++-- .../perfschema/t/dml_performance_timers.test | 1 + .../suite/perfschema/t/dml_setup_timers.test | 1 + mysql-test/suite/perfschema/t/privilege.test | 11 +++++--- mysys/my_rdtsc.c | 25 +++++++++++++++++++ 6 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 mysql-test/suite/perfschema/include/have_timer_cycle.inc diff --git a/mysql-test/suite/perfschema/include/have_timer_cycle.inc b/mysql-test/suite/perfschema/include/have_timer_cycle.inc new file mode 100644 index 00000000000..b801ea256d6 --- /dev/null +++ b/mysql-test/suite/perfschema/include/have_timer_cycle.inc @@ -0,0 +1,4 @@ +if (!`SELECT count(*) FROM performance_schema.performance_timers WHERE timer_name='CYCLE' AND timer_frequency IS NOT NULL`) +{ + Skip Need performance timer CYCLE; +} diff --git a/mysql-test/suite/perfschema/r/privilege.result b/mysql-test/suite/perfschema/r/privilege.result index 49d72fc499f..c5942273057 100644 --- a/mysql-test/suite/perfschema/r/privilege.result +++ b/mysql-test/suite/perfschema/r/privilege.result @@ -554,7 +554,7 @@ ERROR 42000: DROP command denied to user 'pfs_user_4'@'localhost' for table 'eve # # Grant access to change tables with the root account GRANT UPDATE ON performance_schema.setup_consumers TO pfs_user_4; -GRANT UPDATE ON performance_schema.setup_timers TO pfs_user_4; +GRANT UPDATE, SELECT ON performance_schema.setup_timers TO pfs_user_4; GRANT UPDATE, SELECT ON performance_schema.setup_instruments TO pfs_user_4; GRANT DROP ON performance_schema.events_waits_current TO pfs_user_4; GRANT DROP ON performance_schema.events_waits_history TO pfs_user_4; @@ -565,7 +565,7 @@ UPDATE performance_schema.setup_instruments SET enabled = 'YES' WHERE name LIKE 'wait/synch/mutex/%' OR name LIKE 'wait/synch/rwlock/%'; UPDATE performance_schema.setup_consumers SET enabled = 'YES'; -UPDATE performance_schema.setup_timers SET timer_name = 'TICK'; +UPDATE performance_schema.setup_timers SET timer_name = 'TICK' WHERE name <> "wait"; TRUNCATE TABLE performance_schema.events_waits_history_long; TRUNCATE TABLE performance_schema.events_waits_history; TRUNCATE TABLE performance_schema.events_waits_current; @@ -576,6 +576,5 @@ flush privileges; UPDATE performance_schema.setup_instruments SET enabled = 'YES', timed = 'YES'; UPDATE performance_schema.setup_consumers SET enabled = 'YES'; UPDATE performance_schema.setup_timers SET timer_name = 'MICROSECOND' where name="idle"; -UPDATE performance_schema.setup_timers SET timer_name = 'CYCLE' where name="wait"; UPDATE performance_schema.setup_timers SET timer_name = 'NANOSECOND' where name="stage"; UPDATE performance_schema.setup_timers SET timer_name = 'NANOSECOND' where name="statement"; diff --git a/mysql-test/suite/perfschema/t/dml_performance_timers.test b/mysql-test/suite/perfschema/t/dml_performance_timers.test index 2ec37fbe7e9..587c54144aa 100644 --- a/mysql-test/suite/perfschema/t/dml_performance_timers.test +++ b/mysql-test/suite/perfschema/t/dml_performance_timers.test @@ -2,6 +2,7 @@ --source include/not_embedded.inc --source include/have_perfschema.inc +--source include/have_timer_cycle.inc --replace_column 2 3 4 select * from performance_schema.performance_timers; diff --git a/mysql-test/suite/perfschema/t/dml_setup_timers.test b/mysql-test/suite/perfschema/t/dml_setup_timers.test index 641ac90b1c5..bd8822d2b19 100644 --- a/mysql-test/suite/perfschema/t/dml_setup_timers.test +++ b/mysql-test/suite/perfschema/t/dml_setup_timers.test @@ -2,6 +2,7 @@ --source include/not_embedded.inc --source include/have_perfschema.inc +--source include/have_timer_cycle.inc # Set to a known state update performance_schema.setup_timers diff --git a/mysql-test/suite/perfschema/t/privilege.test b/mysql-test/suite/perfschema/t/privilege.test index 1864a34bcfe..926d90d6edc 100644 --- a/mysql-test/suite/perfschema/t/privilege.test +++ b/mysql-test/suite/perfschema/t/privilege.test @@ -291,7 +291,7 @@ TRUNCATE TABLE performance_schema.events_waits_current; --echo # Grant access to change tables with the root account GRANT UPDATE ON performance_schema.setup_consumers TO pfs_user_4; -GRANT UPDATE ON performance_schema.setup_timers TO pfs_user_4; +GRANT UPDATE, SELECT ON performance_schema.setup_timers TO pfs_user_4; GRANT UPDATE, SELECT ON performance_schema.setup_instruments TO pfs_user_4; GRANT DROP ON performance_schema.events_waits_current TO pfs_user_4; GRANT DROP ON performance_schema.events_waits_history TO pfs_user_4; @@ -308,7 +308,11 @@ WHERE name LIKE 'wait/synch/mutex/%' UPDATE performance_schema.setup_consumers SET enabled = 'YES'; -UPDATE performance_schema.setup_timers SET timer_name = 'TICK'; +# We do not touch "wait", to avoid restoring it at the end of the test, +# as its default value initialized at server startup is ambiguous: +# it can be CYCLE or NANOSECOND depending on platform + +UPDATE performance_schema.setup_timers SET timer_name = 'TICK' WHERE name <> "wait"; TRUNCATE TABLE performance_schema.events_waits_history_long; TRUNCATE TABLE performance_schema.events_waits_history; @@ -324,8 +328,9 @@ flush privileges; UPDATE performance_schema.setup_instruments SET enabled = 'YES', timed = 'YES'; UPDATE performance_schema.setup_consumers SET enabled = 'YES'; +# Restore the default values for the timers that we changed. +# Note, we did not touch "wait", see above. UPDATE performance_schema.setup_timers SET timer_name = 'MICROSECOND' where name="idle"; -UPDATE performance_schema.setup_timers SET timer_name = 'CYCLE' where name="wait"; UPDATE performance_schema.setup_timers SET timer_name = 'NANOSECOND' where name="stage"; UPDATE performance_schema.setup_timers SET timer_name = 'NANOSECOND' where name="statement"; diff --git a/mysys/my_rdtsc.c b/mysys/my_rdtsc.c index 028c7f810d4..ad11e8c6a6c 100644 --- a/mysys/my_rdtsc.c +++ b/mysys/my_rdtsc.c @@ -129,6 +129,31 @@ ulonglong my_timer_cycles_il_x86_64(); clock_gettime(CLOCK_SGI_CYCLE) for Irix platforms, or on read_real_time for aix platforms. There is nothing for Alpha platforms, they would be tricky. + + On the platforms that do not have a CYCLE timer, + "wait" events are initialized to use NANOSECOND instead of CYCLE + during performance_schema initialization (at the server startup). + + Linux performance monitor (see "man perf_event_open") can + provide cycle counter on the platforms that do not have + other kinds of cycle counters. But we don't use it so far. + + ARM notes + --------- + During tests on ARMv7 Debian, perf_even_open() based cycle counter provided + too low frequency with too high overhead: + MariaDB [performance_schema]> SELECT * FROM performance_timers; + +-------------+-----------------+------------------+----------------+ + | TIMER_NAME | TIMER_FREQUENCY | TIMER_RESOLUTION | TIMER_OVERHEAD | + +-------------+-----------------+------------------+----------------+ + | CYCLE | 689368159 | 1 | 970 | + | NANOSECOND | 1000000000 | 1 | 308 | + | MICROSECOND | 1000000 | 1 | 417 | + | MILLISECOND | 1000 | 1000 | 407 | + | TICK | 127 | 1 | 612 | + +-------------+-----------------+------------------+----------------+ + Therefore, it was decided not to use perf_even_open() on ARM + (i.e. go without CYCLE and have "wait" events use NANOSECOND by default). */ ulonglong my_timer_cycles(void) From bf186312e19bfe1e1cc5f83fc8280c84b7a17b21 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 30 Oct 2015 13:06:02 +0100 Subject: [PATCH 41/67] fix compilation with -DENABLED_PROFILING=OFF (with ENABLED_PROFILING=ON, field.h was included indirectly from sql_profile.h) --- sql/sql_class.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/sql_class.h b/sql/sql_class.h index b2fa6840439..a94236aec0b 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -27,6 +27,7 @@ #include "log.h" #include "rpl_tblmap.h" #include "mdl.h" +#include "field.h" // Create_field #include "probes_mysql.h" #include "sql_locale.h" /* my_locale_st */ #include "sql_profile.h" /* PROFILING */ From fa1438cbf4307731a54ea4137d5f7d4b744cdfbc Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Tue, 27 Oct 2015 11:17:52 +0100 Subject: [PATCH 42/67] MDEV-8913 Derived queries with same column names as final projection causes issues when using Order By find_item_in_list() now recognize view fields like a fields even if they rever to an expression. The problem of schema name do not taken into account for field with it and derived table fixed. Duplicating code removed --- mysql-test/r/view.result | 41 ++++++++++++++++++++++++++++++++++++++++ mysql-test/t/view.test | 32 +++++++++++++++++++++++++++++++ sql/sql_base.cc | 35 +++++----------------------------- 3 files changed, 78 insertions(+), 30 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index f697f63ca76..347d2841081 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -5699,6 +5699,47 @@ idAlbum strAlbum strMusicBrainzAlbumID strArtists strGenres iYear strMoods strSt 1 strAlbum1 strMusicBrainzAlbumID1 strArtists1 strGenres1 2000 NULL NULL NULL NULL NULL NULL NULL NULL 0 0 album 1 1 strArtist1 strMusicBrainzArtistID 0 0 drop view v1,v2; drop table t1,t2,t3,t4; +# +# MDEV-8913: Derived queries with same column names as final +# projection causes issues when using Order By +# +create table t1 (field int); +insert into t1 values (10),(5),(3),(8),(20); +SELECT sq.f2 AS f1, sq.f1 AS f2 +FROM ( SELECT field AS f1, 1 AS f2 FROM t1) AS sq +ORDER BY sq.f1; +f1 f2 +1 3 +1 5 +1 8 +1 10 +1 20 +create view v1 as SELECT field AS f1, 1 AS f2 FROM t1; +SELECT sq.f2 AS f1, sq.f1 AS f2 +FROM v1 AS sq +ORDER BY sq.f1; +f1 f2 +1 3 +1 5 +1 8 +1 10 +1 20 +drop view v1; +create table t2 SELECT field AS f1, 1 AS f2 FROM t1; +SELECT +sq.f2 AS f1, +sq.f1 AS f2 +FROM t2 AS sq +ORDER BY sq.f1; +f1 f2 +1 3 +1 5 +1 8 +1 10 +1 20 +drop table t1, t2; +SELECT 1 FROM (SELECT 1 as a) AS b HAVING (SELECT `SOME_GARBAGE`.b.a)=1; +ERROR 42S22: Unknown column 'SOME_GARBAGE.b.a' in 'field list' # ----------------------------------------------------------------- # -- End of 10.0 tests. # ----------------------------------------------------------------- diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 773df49de6f..6c99d2217c2 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -5602,6 +5602,38 @@ SELECT v1.*,v2.* FROM v1 LEFT JOIN v2 ON v1.idAlbum = v2.idAlbum WHERE v1.idAlbu drop view v1,v2; drop table t1,t2,t3,t4; +--echo # +--echo # MDEV-8913: Derived queries with same column names as final +--echo # projection causes issues when using Order By +--echo # +create table t1 (field int); +insert into t1 values (10),(5),(3),(8),(20); + +SELECT sq.f2 AS f1, sq.f1 AS f2 +FROM ( SELECT field AS f1, 1 AS f2 FROM t1) AS sq +ORDER BY sq.f1; + +create view v1 as SELECT field AS f1, 1 AS f2 FROM t1; + +SELECT sq.f2 AS f1, sq.f1 AS f2 +FROM v1 AS sq +ORDER BY sq.f1; + +drop view v1; + +create table t2 SELECT field AS f1, 1 AS f2 FROM t1; + +SELECT + sq.f2 AS f1, + sq.f1 AS f2 +FROM t2 AS sq +ORDER BY sq.f1; + +drop table t1, t2; + +--error ER_BAD_FIELD_ERROR +SELECT 1 FROM (SELECT 1 as a) AS b HAVING (SELECT `SOME_GARBAGE`.b.a)=1; + --echo # ----------------------------------------------------------------- --echo # -- End of 10.0 tests. --echo # ----------------------------------------------------------------- diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 8f222761c60..807ec93f4cb 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -6423,6 +6423,7 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list, */ table_name && table_name[0] && (my_strcasecmp(table_alias_charset, table_list->alias, table_name) || + (db_name && db_name[0] && (!table_list->db || !table_list->db[0])) || (db_name && db_name[0] && table_list->db && table_list->db[0] && (table_list->schema_table ? my_strcasecmp(system_charset_info, db_name, table_list->db) : @@ -6896,7 +6897,10 @@ find_item_in_list(Item *find, List &items, uint *counter, for (uint i= 0; (item=li++); i++) { - if (field_name && item->real_item()->type() == Item::FIELD_ITEM) + if (field_name && + (item->real_item()->type() == Item::FIELD_ITEM || + ((item->type() == Item::REF_ITEM) && + (((Item_ref *)item)->ref_type() == Item_ref::VIEW_REF)))) { Item_ident *item_field= (Item_ident*) item; @@ -7022,35 +7026,6 @@ find_item_in_list(Item *find, List &items, uint *counter, break; } } - else if (table_name && item->type() == Item::REF_ITEM && - ((Item_ref *)item)->ref_type() == Item_ref::VIEW_REF) - { - /* - TODO:Here we process prefixed view references only. What we should - really do is process all types of Item_refs. But this will currently - lead to a clash with the way references to outer SELECTs (from the - HAVING clause) are handled in e.g. : - SELECT 1 FROM t1 AS t1_o GROUP BY a - HAVING (SELECT t1_o.a FROM t1 AS t1_i GROUP BY t1_i.a LIMIT 1). - Processing all Item_refs here will cause t1_o.a to resolve to itself. - We still need to process the special case of Item_direct_view_ref - because in the context of views they have the same meaning as - Item_field for tables. - */ - Item_ident *item_ref= (Item_ident *) item; - if (field_name && item_ref->name && item_ref->table_name && - !my_strcasecmp(system_charset_info, item_ref->name, field_name) && - !my_strcasecmp(table_alias_charset, item_ref->table_name, - table_name) && - (!db_name || (item_ref->db_name && - !strcmp (item_ref->db_name, db_name)))) - { - found= li.ref(); - *counter= i; - *resolution= RESOLVED_IGNORING_ALIAS; - break; - } - } } if (!found) { From 245bfc52fc869ce095534b3f0d1f9f559e96d703 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 3 Nov 2015 17:41:06 +0100 Subject: [PATCH 43/67] MDEV-8669 MTR client connections on Windows became much slower. The regression is caused by change bind-address server parameter in MDEV-8083, so now server listens on IPv4 only by default. The problem however is that on Windows, connection to server on localhost appears to be much faster, if server listens on IPv6/dual stack. mysql_real_connect() would try to connect to IPv6 loopback first, and if this fails, the failing connect() call takes several seconds. To fix, use bind-address=* on Windows, and 127.0.0.1 elsewhere --- mysql-test/include/default_mysqld.cnf | 1 - mysql-test/lib/My/ConfigFactory.pm | 8 ++++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/mysql-test/include/default_mysqld.cnf b/mysql-test/include/default_mysqld.cnf index 04321475691..33881666b57 100644 --- a/mysql-test/include/default_mysqld.cnf +++ b/mysql-test/include/default_mysqld.cnf @@ -31,7 +31,6 @@ debug-no-sync # Retry bind as this may fail on busy server port-open-timeout=10 -bind-address=127.0.0.1 log-bin-trust-function-creators=1 key_buffer_size= 1M diff --git a/mysql-test/lib/My/ConfigFactory.pm b/mysql-test/lib/My/ConfigFactory.pm index 4e8507a5c4a..57734fdd87a 100644 --- a/mysql-test/lib/My/ConfigFactory.pm +++ b/mysql-test/lib/My/ConfigFactory.pm @@ -169,6 +169,13 @@ sub fix_log { return "$dir/mysqld.log"; } +sub fix_bind_address { + if (IS_WINDOWS) { + return "*"; + } else { + return "127.0.0.1"; + } +} sub fix_log_slow_queries { my ($self, $config, $group_name, $group)= @_; my $dir= dirname($group->value('datadir')); @@ -251,6 +258,7 @@ my @mysqld_rules= { 'ssl-ca' => \&fix_ssl_ca }, { 'ssl-cert' => \&fix_ssl_server_cert }, { 'ssl-key' => \&fix_ssl_server_key }, + { 'bind-address' => \&fix_bind_address }, ); if (IS_WINDOWS) From d9119710c44d0cd785447080c43bf3c2ba2e4cac Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 3 Nov 2015 18:14:13 +0100 Subject: [PATCH 44/67] MDEV-9041 connect-timeout has no effect on Windows Replaced my_connect() with cross-plattform, timeout aware vio_socket_connect() function --- sql-common/client.c | 189 +------------------------------------------- 1 file changed, 4 insertions(+), 185 deletions(-) diff --git a/sql-common/client.c b/sql-common/client.c index acfdd8531e2..5ffc8c49fea 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -170,188 +170,6 @@ static int get_vio_connect_timeout(MYSQL *mysql) } -/**************************************************************************** - A modified version of connect(). my_connect() allows you to specify - a timeout value, in seconds, that we should wait until we - derermine we can't connect to a particular host. If timeout is 0, - my_connect() will behave exactly like connect(). - - Base version coded by Steve Bernacki, Jr. -*****************************************************************************/ - -int my_connect(my_socket fd, const struct sockaddr *name, uint namelen, - uint timeout) -{ -#if defined(__WIN__) - DBUG_ENTER("my_connect"); - DBUG_RETURN(connect(fd, (struct sockaddr*) name, namelen)); -#else - int flags, res, s_err; - DBUG_ENTER("my_connect"); - DBUG_PRINT("enter", ("fd: %d timeout: %u", fd, timeout)); - - /* - If they passed us a timeout of zero, we should behave - exactly like the normal connect() call does. - */ - - if (timeout == 0) - DBUG_RETURN(connect(fd, (struct sockaddr*) name, namelen)); - - flags = fcntl(fd, F_GETFL, 0); /* Set socket to not block */ -#ifdef O_NONBLOCK - fcntl(fd, F_SETFL, flags | O_NONBLOCK); /* and save the flags.. */ -#endif - - DBUG_PRINT("info", ("connecting non-blocking")); - res= connect(fd, (struct sockaddr*) name, namelen); - DBUG_PRINT("info", ("connect result: %d errno: %d", res, errno)); - s_err= errno; /* Save the error... */ - fcntl(fd, F_SETFL, flags); - if ((res != 0) && (s_err != EINPROGRESS)) - { - errno= s_err; /* Restore it */ - DBUG_RETURN(-1); - } - if (res == 0) /* Connected quickly! */ - DBUG_RETURN(0); - DBUG_RETURN(wait_for_data(fd, timeout)); -#endif -} - - -/* - Wait up to timeout seconds for a connection to be established. - - We prefer to do this with poll() as there is no limitations with this. - If not, we will use select() -*/ - -#if !defined(__WIN__) - -static int wait_for_data(my_socket fd, uint timeout) -{ -#ifdef HAVE_POLL - struct pollfd ufds; - int res; - DBUG_ENTER("wait_for_data"); - - DBUG_PRINT("info", ("polling")); - ufds.fd= fd; - ufds.events= POLLIN | POLLPRI; - if (!(res= poll(&ufds, 1, (int) timeout*1000))) - { - DBUG_PRINT("info", ("poll timed out")); - errno= EINTR; - DBUG_RETURN(-1); - } - DBUG_PRINT("info", - ("poll result: %d errno: %d revents: 0x%02d events: 0x%02d", - res, errno, ufds.revents, ufds.events)); - if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI))) - DBUG_RETURN(-1); - /* - At this point, we know that something happened on the socket. - But this does not means that everything is alright. - The connect might have failed. We need to retrieve the error code - from the socket layer. We must return success only if we are sure - that it was really a success. Otherwise we might prevent the caller - from trying another address to connect to. - */ - { - int s_err; - socklen_t s_len= sizeof(s_err); - - DBUG_PRINT("info", ("Get SO_ERROR from non-blocked connected socket.")); - res= getsockopt(fd, SOL_SOCKET, SO_ERROR, &s_err, &s_len); - DBUG_PRINT("info", ("getsockopt res: %d s_err: %d", res, s_err)); - if (res) - DBUG_RETURN(res); - /* getsockopt() was successful, check the retrieved status value. */ - if (s_err) - { - errno= s_err; - DBUG_RETURN(-1); - } - /* Status from connect() is zero. Socket is successfully connected. */ - } - DBUG_RETURN(0); -#else - SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint); - fd_set sfds; - struct timeval tv; - time_t start_time, now_time; - int res, s_err; - DBUG_ENTER("wait_for_data"); - - if (fd >= FD_SETSIZE) /* Check if wrong error */ - DBUG_RETURN(0); /* Can't use timeout */ - - /* - Our connection is "in progress." We can use the select() call to wait - up to a specified period of time for the connection to suceed. - If select() returns 0 (after waiting howevermany seconds), our socket - never became writable (host is probably unreachable.) Otherwise, if - select() returns 1, then one of two conditions exist: - - 1. An error occured. We use getsockopt() to check for this. - 2. The connection was set up sucessfully: getsockopt() will - return 0 as an error. - - Thanks goes to Andrew Gierth - who posted this method of timing out a connect() in - comp.unix.programmer on August 15th, 1997. - */ - - FD_ZERO(&sfds); - FD_SET(fd, &sfds); - /* - select could be interrupted by a signal, and if it is, - the timeout should be adjusted and the select restarted - to work around OSes that don't restart select and - implementations of select that don't adjust tv upon - failure to reflect the time remaining - */ - start_time= my_time(0); - for (;;) - { - tv.tv_sec = (long) timeout; - tv.tv_usec = 0; -#if defined(HPUX10) - if ((res = select(fd+1, NULL, (int*) &sfds, NULL, &tv)) > 0) - break; -#else - if ((res = select(fd+1, NULL, &sfds, NULL, &tv)) > 0) - break; -#endif - if (res == 0) /* timeout */ - DBUG_RETURN(-1); - now_time= my_time(0); - timeout-= (uint) (now_time - start_time); - if (errno != EINTR || (int) timeout <= 0) - DBUG_RETURN(-1); - } - - /* - select() returned something more interesting than zero, let's - see if we have any errors. If the next two statements pass, - we've got an open socket! - */ - - s_err=0; - if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0) - DBUG_RETURN(-1); - - if (s_err) - { /* getsockopt could succeed */ - errno = s_err; - DBUG_RETURN(-1); /* but return an error... */ - } - DBUG_RETURN(0); /* ok */ -#endif /* HAVE_POLL */ -} -#endif /* !defined(__WIN__) */ - /** Set the internal error message to mysql handler @@ -3165,19 +2983,20 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len, static int connect_sync_or_async(MYSQL *mysql, NET *net, my_socket fd, - const struct sockaddr *name, uint namelen) + struct sockaddr *name, uint namelen) { + int vio_timeout = get_vio_connect_timeout(mysql); + if (mysql->options.extension && mysql->options.extension->async_context && mysql->options.extension->async_context->active) { my_bool old_mode; - int vio_timeout= get_vio_connect_timeout(mysql); vio_blocking(net->vio, FALSE, &old_mode); return my_connect_async(mysql->options.extension->async_context, fd, name, namelen, vio_timeout); } - return my_connect(fd, name, namelen, mysql->options.connect_timeout); + return vio_socket_connect(net->vio, name, namelen, vio_timeout); } From 5041de97e15e4af05003a8c6c14bfff106da570b Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Tue, 3 Nov 2015 09:31:20 +0100 Subject: [PATCH 45/67] MDEV-8701 Crash on derived query Make unique table check after setup_fields of update because unique table can materialize table and we do not need field resolving after materialization. --- mysql-test/r/update.result | 35 ++++++++++++++++++++++++++++++++ mysql-test/t/update.test | 41 ++++++++++++++++++++++++++++++++++++++ sql/sql_prepare.cc | 3 ++- sql/sql_update.cc | 32 ++++++++++++++++++++--------- sql/sql_update.h | 1 + 5 files changed, 102 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result index db7c2380398..2e883aa5680 100644 --- a/mysql-test/r/update.result +++ b/mysql-test/r/update.result @@ -644,4 +644,39 @@ Handler_read_rnd 2 Handler_read_rnd_deleted 0 Handler_read_rnd_next 0 drop table t1, t2; +# +#MDEV-8701: Crash on derived query +# +CREATE TABLE t1 ( +data_exit_entry_id int(11) NOT NULL, +data_entry_id int(11) NOT NULL, +data_entry_exit_id int(11) NOT NULL, +data_exit_entry_quantity double NOT NULL +) DEFAULT CHARSET=utf8; +CREATE TABLE t2 ( +data_entry_id int(11) NOT NULL, +data_entry_cost double NOT NULL, +data_entry_quantity double NOT NULL +) DEFAULT CHARSET=utf8; +create algorithm=temptable view v1 as SELECT data_entry_exit_id, data_exit_entry_quantity, data_entry_cost +FROM t1 INNER JOIN t2 as dt ON dt.data_entry_id = t1.data_entry_id; +UPDATE t2 +SET data_entry_cost += ( ( SELECT SUM(data_exit_entry_quantity * data_entry_cost) +FROM +v1 AS query +WHERE data_entry_exit_id = t2.data_entry_id +) +); +UPDATE t2 +SET data_entry_cost += ( ( SELECT SUM(data_exit_entry_quantity * data_entry_cost) +FROM +( SELECT data_entry_exit_id, data_exit_entry_quantity, data_entry_cost +FROM t1 INNER JOIN t2 as dt ON dt.data_entry_id = t1.data_entry_id) AS query +WHERE data_entry_exit_id = t2.data_entry_id +) +); +drop view v1; +drop table t1, t2; # End of MariaDB 10.0 tests diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test index 05f9ce39bec..c0334a75bff 100644 --- a/mysql-test/t/update.test +++ b/mysql-test/t/update.test @@ -580,4 +580,45 @@ show status like 'Handler_read%'; drop table t1, t2; +--echo # +--echo #MDEV-8701: Crash on derived query +--echo # + +CREATE TABLE t1 ( + data_exit_entry_id int(11) NOT NULL, + data_entry_id int(11) NOT NULL, + data_entry_exit_id int(11) NOT NULL, + data_exit_entry_quantity double NOT NULL +) DEFAULT CHARSET=utf8; + +CREATE TABLE t2 ( + data_entry_id int(11) NOT NULL, + data_entry_cost double NOT NULL, + data_entry_quantity double NOT NULL +) DEFAULT CHARSET=utf8; + +create algorithm=temptable view v1 as SELECT data_entry_exit_id, data_exit_entry_quantity, data_entry_cost + FROM t1 INNER JOIN t2 as dt ON dt.data_entry_id = t1.data_entry_id; + +UPDATE t2 +SET data_entry_cost + = ( ( SELECT SUM(data_exit_entry_quantity * data_entry_cost) + FROM + v1 AS query + WHERE data_entry_exit_id = t2.data_entry_id + ) + ); + +UPDATE t2 +SET data_entry_cost + = ( ( SELECT SUM(data_exit_entry_quantity * data_entry_cost) + FROM + ( SELECT data_entry_exit_id, data_exit_entry_quantity, data_entry_cost + FROM t1 INNER JOIN t2 as dt ON dt.data_entry_id = t1.data_entry_id) AS query + WHERE data_entry_exit_id = t2.data_entry_id + ) + ); + +drop view v1; +drop table t1, t2; --echo # End of MariaDB 10.0 tests diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 1790b972724..8a3c55cbfda 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1420,7 +1420,8 @@ static int mysql_test_update(Prepared_statement *stmt, (SELECT_ACL & ~table_list->table->grant.privilege); table_list->register_want_access(SELECT_ACL); #endif - if (setup_fields(thd, 0, stmt->lex->value_list, MARK_COLUMNS_NONE, 0, 0)) + if (setup_fields(thd, 0, stmt->lex->value_list, MARK_COLUMNS_NONE, 0, 0) || + check_unique_table(thd, table_list)) goto error; /* TODO: here we should send types of placeholders to the client. */ DBUG_RETURN(0); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index d3d222620a8..0f7b28cd9d9 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -364,6 +364,9 @@ int mysql_update(THD *thd, DBUG_RETURN(1); /* purecov: inspected */ } + if (check_unique_table(thd, table_list)) + DBUG_RETURN(TRUE); + /* Apply the IN=>EXISTS transformation to all subqueries and optimize them. */ if (select_lex->optimize_unflattened_subqueries(false)) DBUG_RETURN(TRUE); @@ -1095,19 +1098,30 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, setup_ftfuncs(select_lex)) DBUG_RETURN(TRUE); - /* Check that we are not using table that we are updating in a sub select */ - { - TABLE_LIST *duplicate; - if ((duplicate= unique_table(thd, table_list, table_list->next_global, 0))) - { - update_non_unique_table_error(table_list, "UPDATE", duplicate); - DBUG_RETURN(TRUE); - } - } select_lex->fix_prepare_information(thd, conds, &fake_conds); DBUG_RETURN(FALSE); } +/** + Check that we are not using table that we are updating in a sub select + + @param thd Thread handle + @param table_list List of table with first to check + + @retval TRUE Error + @retval FALSE OK +*/ +bool check_unique_table(THD *thd, TABLE_LIST *table_list) +{ + TABLE_LIST *duplicate; + DBUG_ENTER("check_unique_table"); + if ((duplicate= unique_table(thd, table_list, table_list->next_global, 0))) + { + update_non_unique_table_error(table_list, "UPDATE", duplicate); + DBUG_RETURN(TRUE); + } + DBUG_RETURN(FALSE); +} /*************************************************************************** Update multiple tables from join diff --git a/sql/sql_update.h b/sql/sql_update.h index 64029c5d634..4c6f89d8468 100644 --- a/sql/sql_update.h +++ b/sql/sql_update.h @@ -27,6 +27,7 @@ typedef class st_select_lex_unit SELECT_LEX_UNIT; bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, Item **conds, uint order_num, ORDER *order); +bool check_unique_table(THD *thd, TABLE_LIST *table_list); int mysql_update(THD *thd,TABLE_LIST *tables,List &fields, List &values,COND *conds, uint order_num, ORDER *order, ha_rows limit, From a36048d143c2e3cd956009849dc28f4a714d00d0 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 6 Nov 2015 12:26:03 +0400 Subject: [PATCH 46/67] MDEV-7550 TokuDB crashes in build tests on Launchpad When compiled with "-Wl,-Bsymbolic-functions" flags (e.g. when building a .deb package on Ubuntu) with TokuDB and jemalloc, mysqld crashed in toku_get_processor_frequency_cpuinfo() when free()-ing a buffer returned by getline(). getline() uses libc malloc() internally, while free() is aliased to jemalloc's free() in this configuration. Fixing not to use getline(). Using a static buffer instead. --- .../tokudb/ft-index/portability/portability.cc | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/storage/tokudb/ft-index/portability/portability.cc b/storage/tokudb/ft-index/portability/portability.cc index 09c1ccd50be..a6522b3c5b9 100644 --- a/storage/tokudb/ft-index/portability/portability.cc +++ b/storage/tokudb/ft-index/portability/portability.cc @@ -355,9 +355,16 @@ toku_get_processor_frequency_cpuinfo(uint64_t *hzret) { r = get_error_errno(); } else { uint64_t maxhz = 0; - char *buf = NULL; - size_t n = 0; - while (getline(&buf, &n, fp) >= 0) { + /* + Some lines in the "/proc/cpuinfo" output can be long, e.g.: + "flags : fpu vme de pse tsc ms .... smep erms" + In case a line does not fit into "buf", it will be read + in parts by multiple "fgets" calls. This is ok, as + it is very unlikely that a non-leading substring of a line + will match again the pattern "processor: %u". + */ + char buf[512]; + while (fgets(buf, (int) sizeof(buf), fp) != NULL) { unsigned int cpu; sscanf(buf, "processor : %u", &cpu); unsigned int ma, mb; @@ -367,8 +374,6 @@ toku_get_processor_frequency_cpuinfo(uint64_t *hzret) { maxhz = hz; } } - if (buf) - free(buf); fclose(fp); *hzret = maxhz; r = maxhz == 0 ? ENOENT : 0;; From f1daf9ced46ba65b025a92f512833c86d04e7cf2 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 6 Nov 2015 17:24:23 +0100 Subject: [PATCH 47/67] MDEV-9024 Build fails with VS2015 Fix build failures caused by new C runtime library - isnan, snprintf, struct timespec are now defined, attempt to redefine them leads - P_tmpdir, tzname are no more defined - lfind() and lsearch() in lf_hash.c had to be renamed, declaration conflicts with some C runtime functions with the same name declared in a header included by stdlib.h Also fix couple of annoying warnings : - remove #define NOMINMAX from config.h to avoid "redefined" compiler warnings(NOMINMAX is already in compile flags) - disable incremental linker in Debug as well (feature not used much and compiler crashes often) Also simplify package building with Wix, require Wix 3.9 or later (VS2015 is not compatible with old Wix 3.5/3.6) --- client/mysql.cc | 2 +- client/mysqltest.cc | 2 +- cmake/os/Windows.cmake | 11 +++-- cmake/os/WindowsCache.cmake | 4 -- config.h.cmake | 8 +++- configure.cmake | 2 + include/hash.h | 4 +- include/my_pthread.h | 2 + libmysql/errmsg.c | 2 +- mysys/hash.c | 2 +- mysys/lf_hash.c | 40 ++++++++--------- win/packaging/CMakeLists.txt | 78 ++++++++++++++++++++++----------- win/packaging/ca/CMakeLists.txt | 42 +----------------- 13 files changed, 97 insertions(+), 102 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 60bed6b0d6a..71eac780262 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1108,7 +1108,7 @@ inline int get_command_index(char cmd_char) All client-specific commands are in the first part of commands array and have a function to implement it. */ - for (uint i= 0; *commands[i].func; i++) + for (uint i= 0; commands[i].func; i++) if (commands[i].cmd_char == cmd_char) return i; return -1; diff --git a/client/mysqltest.cc b/client/mysqltest.cc index e28d56e9187..c601fb57f2f 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -5246,7 +5246,7 @@ static st_error global_error_names[] = #include static st_error handler_error_names[] = { - { "", -1U, "" }, + { "", UINT_MAX, "" }, #include { 0, 0, 0 } }; diff --git a/cmake/os/Windows.cmake b/cmake/os/Windows.cmake index 4c01bab4c1f..1ad7e5c288d 100644 --- a/cmake/os/Windows.cmake +++ b/cmake/os/Windows.cmake @@ -96,8 +96,11 @@ IF(MSVC) STRING(REGEX REPLACE "/STACK:([^ ]+)" "" CMAKE_${type}_LINKER_FLAGS "${CMAKE_${type}_LINKER_FLAGS}") STRING(REGEX REPLACE "/INCREMENTAL:([^ ]+)" "/INCREMENTAL:NO" CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO}") STRING(REGEX REPLACE "/INCREMENTAL$" "/INCREMENTAL:NO" CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO}") + STRING(REGEX REPLACE "/INCREMENTAL:([^ ]+)" "/INCREMENTAL:NO" CMAKE_${type}_LINKER_FLAGS_DEBUG "${CMAKE_${type}_LINKER_FLAGS_DEBUG}") + STRING(REGEX REPLACE "/INCREMENTAL$" "/INCREMENTAL:NO" CMAKE_${type}_LINKER_FLAGS_DEBUG "${CMAKE_${type}_LINKER_FLAGS_DEBUG}") SET(CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO} /OPT:REF /release") ENDFOREACH() + # Mark 32 bit executables large address aware so they can # use > 2GB address space @@ -113,7 +116,7 @@ IF(MSVC) #TODO: update the code and remove the disabled warnings SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4800 /wd4805 /wd4996") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4800 /wd4805 /wd4996 /we4099") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4800 /wd4805 /wd4996 /wd4291 /we4099") IF(CMAKE_SIZEOF_VOID_P MATCHES 8) # _WIN64 is defined by the compiler itself. @@ -181,14 +184,14 @@ CHECK_SYMBOL_REPLACEMENT(S_IROTH _S_IREAD sys/stat.h) CHECK_SYMBOL_REPLACEMENT(S_IFIFO _S_IFIFO sys/stat.h) CHECK_SYMBOL_REPLACEMENT(SIGQUIT SIGTERM signal.h) CHECK_SYMBOL_REPLACEMENT(SIGPIPE SIGINT signal.h) -CHECK_SYMBOL_REPLACEMENT(isnan _isnan float.h) -CHECK_SYMBOL_REPLACEMENT(finite _finite float.h) +CHECK_SYMBOL_REPLACEMENT(isnan _isnan "math.h;float.h") +CHECK_SYMBOL_REPLACEMENT(finite _finite "math;float.h") CHECK_FUNCTION_REPLACEMENT(popen _popen) CHECK_FUNCTION_REPLACEMENT(pclose _pclose) CHECK_FUNCTION_REPLACEMENT(access _access) CHECK_FUNCTION_REPLACEMENT(strcasecmp _stricmp) CHECK_FUNCTION_REPLACEMENT(strncasecmp _strnicmp) -CHECK_FUNCTION_REPLACEMENT(snprintf _snprintf) +CHECK_SYMBOL_REPLACEMENT(snprintf _snprintf stdio.h) CHECK_FUNCTION_REPLACEMENT(strtok_r strtok_s) CHECK_FUNCTION_REPLACEMENT(strtoll _strtoi64) CHECK_FUNCTION_REPLACEMENT(strtoull _strtoui64) diff --git a/cmake/os/WindowsCache.cmake b/cmake/os/WindowsCache.cmake index b805ec4fb43..2808a6f749f 100644 --- a/cmake/os/WindowsCache.cmake +++ b/cmake/os/WindowsCache.cmake @@ -101,7 +101,6 @@ SET(HAVE_IPPROTO_IPV6 CACHE INTERNAL "") SET(HAVE_IPV6 TRUE CACHE INTERNAL "") SET(HAVE_IPV6_V6ONLY 1 CACHE INTERNAL "") SET(HAVE_ISINF CACHE INTERNAL "") -SET(HAVE_ISNAN CACHE INTERNAL "") SET(HAVE_ISSETUGID CACHE INTERNAL "") SET(HAVE_GETUID CACHE INTERNAL "") SET(HAVE_GETEUID CACHE INTERNAL "") @@ -231,7 +230,6 @@ SET(HAVE_SIZEOF_ULONG FALSE CACHE INTERNAL "") SET(HAVE_SIZEOF_U_INT32_T FALSE CACHE INTERNAL "") SET(HAVE_SIZE_OF_SSIZE_T FALSE CACHE INTERNAL "") SET(HAVE_SLEEP CACHE INTERNAL "") -SET(HAVE_SNPRINTF CACHE INTERNAL "") SET(HAVE_SOCKADDR_STORAGE_SS_FAMILY 1 CACHE INTERNAL "") SET(HAVE_SOLARIS_STYLE_GETHOST CACHE INTERNAL "") SET(STACK_DIRECTION -1 CACHE INTERNAL "") @@ -324,10 +322,8 @@ SET(WORDS_BIGENDIAN CACHE INTERNAL "") SET(HAVE__S_IFIFO 1 CACHE INTERNAL "") SET(HAVE__S_IREAD 1 CACHE INTERNAL "") SET(HAVE__finite 1 CACHE INTERNAL "") -SET(HAVE__isnan 1 CACHE INTERNAL "") SET(HAVE__pclose 1 CACHE INTERNAL "") SET(HAVE__popen 1 CACHE INTERNAL "") -SET(HAVE__snprintf 1 CACHE INTERNAL "") SET(HAVE__stricmp 1 CACHE INTERNAL "") SET(HAVE__strnicmp 1 CACHE INTERNAL "") SET(HAVE__strtoi64 1 CACHE INTERNAL "") diff --git a/config.h.cmake b/config.h.cmake index 46eed79dfa5..b037464df88 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -317,6 +317,8 @@ #cmakedefine HAVE_TIMESPEC_TS_SEC 1 #cmakedefine STRUCT_DIRENT_HAS_D_INO 1 #cmakedefine STRUCT_DIRENT_HAS_D_NAMLEN 1 +#cmakedefine STRUCT_TIMESPEC_HAS_TV_SEC 1 +#cmakedefine STRUCT_TIMESPEC_HAS_TV_NSEC 1 #cmakedefine SPRINTF_RETURNS_INT 1 #define USE_MB 1 @@ -514,6 +516,10 @@ #cmakedefine strtoll @strtoll@ #cmakedefine strtoull @strtoull@ #cmakedefine vsnprintf @vsnprintf@ +#if (_MSC_VER > 1800) +#define tzname _tzname +#define P_tmpdir "C:\\TEMP" +#endif #if (_MSC_VER > 1310) # define HAVE_SETENV #define setenv(a,b,c) _putenv_s(a,b) @@ -522,7 +528,7 @@ /* We don't want the min/max macros */ #ifdef __WIN__ -#define NOMINMAX +#define NOMINMAX 1 #endif /* diff --git a/configure.cmake b/configure.cmake index fb127688bd2..f8c58dac391 100644 --- a/configure.cmake +++ b/configure.cmake @@ -1056,3 +1056,5 @@ CHECK_STRUCT_HAS_MEMBER("struct dirent" d_ino "dirent.h" STRUCT_DIRENT_HAS_D_IN CHECK_STRUCT_HAS_MEMBER("struct dirent" d_namlen "dirent.h" STRUCT_DIRENT_HAS_D_NAMLEN) SET(SPRINTF_RETURNS_INT 1) CHECK_INCLUDE_FILE(ucontext.h HAVE_UCONTEXT_H) +CHECK_STRUCT_HAS_MEMBER("struct timespec" tv_sec "time.h" STRUCT_TIMESPEC_HAS_TV_SEC) +CHECK_STRUCT_HAS_MEMBER("struct timespec" tv_nsec "time.h" STRUCT_TIMESPEC_HAS_TV_NSEC) diff --git a/include/hash.h b/include/hash.h index ba36df23f58..fde7fc30d38 100644 --- a/include/hash.h +++ b/include/hash.h @@ -44,7 +44,7 @@ extern "C" { typedef uint my_hash_value_type; typedef uchar *(*my_hash_get_key)(const uchar *,size_t*,my_bool); -typedef my_hash_value_type (*my_hash_function)(const CHARSET_INFO *, +typedef my_hash_value_type (*my_hash_function)(CHARSET_INFO *, const uchar *, size_t); typedef void (*my_hash_free_key)(void *); typedef my_bool (*my_hash_walk_action)(void *,void *); @@ -78,7 +78,7 @@ uchar *my_hash_search(const HASH *info, const uchar *key, size_t length); uchar *my_hash_search_using_hash_value(const HASH *info, my_hash_value_type hash_value, const uchar *key, size_t length); -my_hash_value_type my_hash_sort(const CHARSET_INFO *cs, +my_hash_value_type my_hash_sort(CHARSET_INFO *cs, const uchar *key, size_t length); #define my_calc_hash(A, B, C) my_hash_sort((A)->charset, B, C) uchar *my_hash_first(const HASH *info, const uchar *key, size_t length, diff --git a/include/my_pthread.h b/include/my_pthread.h index bb4d0c88ebd..cff6416904a 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -86,10 +86,12 @@ typedef volatile LONG my_pthread_once_t; #define MY_PTHREAD_ONCE_INPROGRESS 1 #define MY_PTHREAD_ONCE_DONE 2 +#if !STRUCT_TIMESPEC_HAS_TV_SEC || !STRUCT_TIMESPEC_HAS_TV_NSEC struct timespec { time_t tv_sec; long tv_nsec; }; +#endif int win_pthread_mutex_trylock(pthread_mutex_t *mutex); int pthread_create(pthread_t *, const pthread_attr_t *, pthread_handler, void *); diff --git a/libmysql/errmsg.c b/libmysql/errmsg.c index 84884f9565a..e30cdc9762b 100644 --- a/libmysql/errmsg.c +++ b/libmysql/errmsg.c @@ -90,7 +90,7 @@ const char *client_errors[]= "" }; -const char** get_client_errmsgs() +const char** get_client_errmsgs(void) { return client_errors; } diff --git a/mysys/hash.c b/mysys/hash.c index 4ef731cde15..344b698a433 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -40,7 +40,7 @@ static void movelink(HASH_LINK *array,uint pos,uint next_link,uint newlink); static int hashcmp(const HASH *hash, HASH_LINK *pos, const uchar *key, size_t length); -my_hash_value_type my_hash_sort(const CHARSET_INFO *cs, const uchar *key, +my_hash_value_type my_hash_sort(CHARSET_INFO *cs, const uchar *key, size_t length) { ulong nr1= 1, nr2= 4; diff --git a/mysys/lf_hash.c b/mysys/lf_hash.c index aa96ca94198..eb0c252edb1 100644 --- a/mysys/lf_hash.c +++ b/mysys/lf_hash.c @@ -43,7 +43,7 @@ const int LF_HASH_OVERHEAD= sizeof(LF_SLIST); /* a structure to pass the context (pointers two the three successive elements - in a list) from lfind to linsert/ldelete + in a list) from l_find to l_insert/l_delete */ typedef struct { intptr volatile *prev; @@ -70,7 +70,7 @@ typedef struct { cursor is positioned in either case pins[0..2] are used, they are NOT removed on return */ -static int lfind(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr, +static int l_find(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr, const uchar *key, uint keylen, CURSOR *cursor, LF_PINS *pins) { uint32 cur_hashnr; @@ -138,7 +138,7 @@ retry: /* DESCRIPTION insert a 'node' in the list that starts from 'head' in the correct - position (as found by lfind) + position (as found by l_find) RETURN 0 - inserted @@ -148,7 +148,7 @@ retry: it uses pins[0..2], on return all pins are removed. if there're nodes with the same key value, a new node is added before them. */ -static LF_SLIST *linsert(LF_SLIST * volatile *head, CHARSET_INFO *cs, +static LF_SLIST *l_insert(LF_SLIST * volatile *head, CHARSET_INFO *cs, LF_SLIST *node, LF_PINS *pins, uint flags) { CURSOR cursor; @@ -156,7 +156,7 @@ static LF_SLIST *linsert(LF_SLIST * volatile *head, CHARSET_INFO *cs, for (;;) { - if (lfind(head, cs, node->hashnr, node->key, node->keylen, + if (l_find(head, cs, node->hashnr, node->key, node->keylen, &cursor, pins) && (flags & LF_HASH_UNIQUE)) { @@ -200,7 +200,7 @@ static LF_SLIST *linsert(LF_SLIST * volatile *head, CHARSET_INFO *cs, NOTE it uses pins[0..2], on return all pins are removed. */ -static int ldelete(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr, +static int l_delete(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr, const uchar *key, uint keylen, LF_PINS *pins) { CURSOR cursor; @@ -208,7 +208,7 @@ static int ldelete(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr, for (;;) { - if (!lfind(head, cs, hashnr, key, keylen, &cursor, pins)) + if (!l_find(head, cs, hashnr, key, keylen, &cursor, pins)) { res= 1; /* not found */ break; @@ -232,7 +232,7 @@ static int ldelete(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr, (to ensure the number of "set DELETED flag" actions is equal to the number of "remove from the list" actions) */ - lfind(head, cs, hashnr, key, keylen, &cursor, pins); + l_find(head, cs, hashnr, key, keylen, &cursor, pins); } res= 0; break; @@ -258,12 +258,12 @@ static int ldelete(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr, it uses pins[0..2], on return the pin[2] keeps the node found all other pins are removed. */ -static LF_SLIST *lsearch(LF_SLIST * volatile *head, CHARSET_INFO *cs, +static LF_SLIST *l_search(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr, const uchar *key, uint keylen, LF_PINS *pins) { CURSOR cursor; - int res= lfind(head, cs, hashnr, key, keylen, &cursor, pins); + int res= l_find(head, cs, hashnr, key, keylen, &cursor, pins); if (res) _lf_pin(pins, 2, cursor.curr); else @@ -363,7 +363,7 @@ void lf_hash_destroy(LF_HASH *hash) -1 - out of memory NOTE - see linsert() for pin usage notes + see l_insert() for pin usage notes */ int lf_hash_insert(LF_HASH *hash, LF_PINS *pins, const void *data) { @@ -384,7 +384,7 @@ int lf_hash_insert(LF_HASH *hash, LF_PINS *pins, const void *data) if (*el == NULL && unlikely(initialize_bucket(hash, el, bucket, pins))) return -1; node->hashnr= my_reverse_bits(hashnr) | 1; /* normal node */ - if (linsert(el, hash->charset, node, pins, hash->flags)) + if (l_insert(el, hash->charset, node, pins, hash->flags)) { _lf_alloc_free(pins, node); lf_rwunlock_by_pins(pins); @@ -407,7 +407,7 @@ int lf_hash_insert(LF_HASH *hash, LF_PINS *pins, const void *data) 1 - didn't (not found) -1 - out of memory NOTE - see ldelete() for pin usage notes + see l_delete() for pin usage notes */ int lf_hash_delete(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen) { @@ -427,7 +427,7 @@ int lf_hash_delete(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen) */ if (*el == NULL && unlikely(initialize_bucket(hash, el, bucket, pins))) return -1; - if (ldelete(el, hash->charset, my_reverse_bits(hashnr) | 1, + if (l_delete(el, hash->charset, my_reverse_bits(hashnr) | 1, (uchar *)key, keylen, pins)) { lf_rwunlock_by_pins(pins); @@ -446,7 +446,7 @@ int lf_hash_delete(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen) MY_ERRPTR if OOM NOTE - see lsearch() for pin usage notes + see l_search() for pin usage notes */ void *lf_hash_search(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen) { @@ -460,7 +460,7 @@ void *lf_hash_search(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen) return MY_ERRPTR; if (*el == NULL && unlikely(initialize_bucket(hash, el, bucket, pins))) return MY_ERRPTR; - found= lsearch(el, hash->charset, my_reverse_bits(hashnr) | 1, + found= l_search(el, hash->charset, my_reverse_bits(hashnr) | 1, (uchar *)key, keylen, pins); lf_rwunlock_by_pins(pins); return found ? found+1 : 0; @@ -488,16 +488,16 @@ static int initialize_bucket(LF_HASH *hash, LF_SLIST * volatile *node, dummy->hashnr= my_reverse_bits(bucket) | 0; /* dummy node */ dummy->key= dummy_key; dummy->keylen= 0; - if ((cur= linsert(el, hash->charset, dummy, pins, LF_HASH_UNIQUE))) + if ((cur= l_insert(el, hash->charset, dummy, pins, LF_HASH_UNIQUE))) { my_free(dummy); dummy= cur; } my_atomic_casptr((void **)node, (void **)(char*) &tmp, dummy); /* - note that if the CAS above failed (after linsert() succeeded), - it would mean that some other thread has executed linsert() for - the same dummy node, its linsert() failed, it picked up our + note that if the CAS above failed (after l_insert() succeeded), + it would mean that some other thread has executed l_insert() for + the same dummy node, its l_insert() failed, it picked up our dummy node (in "dummy= cur") and executed the same CAS as above. Which means that even if CAS above failed we don't need to retry, and we should not free(dummy) - there's no memory leak here diff --git a/win/packaging/CMakeLists.txt b/win/packaging/CMakeLists.txt index 3b9b72f48fd..0535a486d57 100644 --- a/win/packaging/CMakeLists.txt +++ b/win/packaging/CMakeLists.txt @@ -17,36 +17,62 @@ IF(NOT WIN32) RETURN() ENDIF() -SET(MANUFACTURER "MariaDB Corporation Ab") -FIND_PATH(WIX_DIR heat.exe - $ENV{WIX_DIR}/bin - $ENV{ProgramFiles}/wix/bin - "$ENV{ProgramFiles}/Windows Installer XML v3/bin" - "$ENV{ProgramFiles}/Windows Installer XML v3.5/bin" - "$ENV{ProgramFiles}/Windows Installer XML v3.6/bin" - "$ENV{ProgramFiles}/WiX Toolset v3.9/bin" - "$ENV{WIX}/bin" -) - -SET(CPACK_WIX_PACKAGE_BASE_NAME "MariaDB") -IF(CMAKE_SIZEOF_VOID_P EQUAL 4) - SET(CPACK_WIX_UPGRADE_CODE "49EB7A6A-1CEF-4A1E-9E89-B9A4993963E3") - SET(CPACK_WIX_PACKAGE_NAME "MariaDB @MAJOR_VERSION@.@MINOR_VERSION@") -ELSE() - SET(CPACK_WIX_UPGRADE_CODE "2331E7BD-EE58-431B-9E18-B2B918BCEB1B") - SET(CPACK_WIX_PACKAGE_NAME "MariaDB @MAJOR_VERSION@.@MINOR_VERSION@ (x64)") +IF(MSVC_VERSION LESS 1600) + RETURN() ENDIF() -IF(NOT WIX_DIR) - IF(NOT _WIX_DIR_CHECKED) - SET(_WIX_DIR_CHECKED 1 CACHE INTERNAL "") - MESSAGE(STATUS "Cannot find wix 3, installer project will not be generated") - IF(BUILD_RELEASE) + +SET(MANUFACTURER "MariaDB Corporation Ab") +FIND_PATH(WIX_DIR heat.exe + "$ENV{ProgramFiles}/WiX Toolset v3.9/bin" + "$ENV{ProgramFiles}/WiX Toolset v3.10/bin" +) +SET(CPACK_WIX_PACKAGE_BASE_NAME "MariaDB") +IF(CMAKE_SIZEOF_VOID_P EQUAL 4) + SET(CPACK_WIX_UPGRADE_CODE "49EB7A6A-1CEF-4A1E-9E89-B9A4993963E3") + SET(CPACK_WIX_PACKAGE_NAME "MariaDB ${MAJOR_VERSION}.${MINOR_VERSION}") +ELSE() + SET(CPACK_WIX_UPGRADE_CODE "2331E7BD-EE58-431B-9E18-B2B918BCEB1B") + SET(CPACK_WIX_PACKAGE_NAME "MariaDB ${MAJOR_VERSION}.${MINOR_VERSION} (x64)") +ENDIF() + +IF(WIX_DIR) +IF(CMAKE_SIZEOF_VOID_P EQUAL 8) + SET(WIX_ARCH_SUFFIX "x64") +ELSE() + SET(WIX_ARCH_SUFFIX "x86") +ENDIF() +# Need some Wix SDK libraries to link with customaction +IF(MSVC_VERSION EQUAL 1600 OR MSVC_VERSION EQUAL 1700 ) + SET(WIX_MSVC_SUFFIX "VS2010") +ELSEIF(MSVC_VERSION EQUAL 1800) + SET(WIX_MSVC_SUFFIX "VS2013") +ELSEIF (MSVC_VERSION EQUAL 1900) + SET(WIX_MSVC_SUFFIX "VS2015") +ENDIF() + + +FIND_LIBRARY(WIX_WCAUTIL_LIBRARY + NAMES wcautil${WIX_ARCH_SUFFIX} wcautil${WIX_MSVC_SUFFIX}${WIX_ARCH_SUFFIX} + wcautil + PATHS + ${WIX_DIR}/../SDK/${WIX_MSVC_SUFFIX}/lib/${WIX_ARCH_SUFFIX} + ) + +FIND_LIBRARY(WIX_DUTIL_LIBRARY + NAMES dutil${WIX_ARCH_SUFFIX} + dutil + PATHS + ${WIX_DIR}/../SDK/${WIX_MSVC_SUFFIX}/lib/${WIX_ARCH_SUFFIX} + ) +ENDIF() + +IF(NOT WIX_DUTIL_LIBRARY) + MESSAGE(STATUS "Cannot find wix 3, installer project will not be generated") + IF(BUILD_RELEASE) MESSAGE(FATAL_ERROR - "Can't find Wix. It is necessary for producing official package" - ) - ENDIF() + "Can't find Wix. It is necessary for producing official package") ENDIF() RETURN() ENDIF() diff --git a/win/packaging/ca/CMakeLists.txt b/win/packaging/ca/CMakeLists.txt index ccd03130d69..c57ae4b2113 100644 --- a/win/packaging/ca/CMakeLists.txt +++ b/win/packaging/ca/CMakeLists.txt @@ -13,53 +13,13 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -INCLUDE_DIRECTORIES(${WIX_DIR}/../SDK/inc) -LINK_DIRECTORIES(${WIX_DIR}/../SDK/lib) - +INCLUDE_DIRECTORIES(${WIX_DIR}/../SDK/${WIX_MSVC_SUFFIX}/inc) SET(WIXCA_SOURCES CustomAction.cpp CustomAction.def) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql) -IF(CMAKE_SIZEOF_VOID_P EQUAL 8) - SET(WIX_ARCH_SUFFIX "_x64") - SET(WIX36_ARCH_SUFFIX "x64") -ELSE() - SET(WIX_ARCH_SUFFIX) - SET(WIX36_ARCH_SUFFIX "x86") -ENDIF() -IF(MSVC_VERSION EQUAL 1400) - SET(WIX35_MSVC_SUFFIX "_2005") -ELSEIF(MSVC_VERSION EQUAL 1500) - SET(WIX35_MSVC_SUFFIX "_2008") - SET(WIX36_MSVC_SUFFIX "VS2008") -ELSEIF(MSVC_VERSION EQUAL 1600 OR MSVC_VERSION EQUAL 1700 ) - SET(WIX35_MSVC_SUFFIX "_2010") - SET(WIX36_MSVC_SUFFIX "VS2010") -ELSEIF(MSVC_VERSION EQUAL 1800 OR MSVC_VERSION EQUAL 1900 ) - SET(WIX35_MSVC_SUFFIX "_2013") - SET(WIX36_MSVC_SUFFIX "VS2013") -ELSE() - # When next VS is out, add the correct version here - MESSAGE(FATAL_ERROR "Unknown VS version") -ENDIF() -INCLUDE_DIRECTORIES(${WIX_DIR}/../SDK/${WIX36_MSVC_SUFFIX}/inc) -FIND_LIBRARY(WIX_WCAUTIL_LIBRARY - NAMES wcautil${WIX_ARCH_SUFFIX} wcautil${WIX35_MSVC_SUFFIX}${WIX_ARCH_SUFFIX} - wcautil - PATHS - ${WIX_DIR}/../SDK/lib - ${WIX_DIR}/../SDK/${WIX36_MSVC_SUFFIX}/lib/${WIX36_ARCH_SUFFIX} - ) - -FIND_LIBRARY(WIX_DUTIL_LIBRARY - NAMES dutil${WIX_ARCH_SUFFIX} dutil${WIX35_MSVC_SUFFIX}${WIX_ARCH_SUFFIX} - dutil - PATHS - ${WIX_DIR}/../SDK/lib - ${WIX_DIR}/../SDK/${WIX36_MSVC_SUFFIX}/lib/${WIX36_ARCH_SUFFIX} - ) ADD_VERSION_INFO(wixca SHARED WIXCA_SOURCES) ADD_LIBRARY(wixca SHARED EXCLUDE_FROM_ALL ${WIXCA_SOURCES}) From c88ca2c22739dc2327c7b1082df79a93370662ba Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Fri, 6 Nov 2015 17:56:56 +0100 Subject: [PATCH 48/67] MDEV-8701 Crash on derived query MDEV-8938 Server Crash on Update with joins Make unique table check after setup_fields of update because unique table can materialize table and we do not need field resolving after materialization. --- mysql-test/r/update.result | 59 ++++++++++++++++++++++++++++++ mysql-test/t/update.test | 73 ++++++++++++++++++++++++++++++++++++++ sql/sql_prepare.cc | 3 +- sql/sql_update.cc | 32 ++++++++++++----- sql/sql_update.h | 1 + 5 files changed, 158 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result index 3ea58553653..0b036ca0a2e 100644 --- a/mysql-test/r/update.result +++ b/mysql-test/r/update.result @@ -618,3 +618,62 @@ Variable_name Value Handler_update 5 ROLLBACK; DROP TABLE t1, t2; +# +# MDEV-8938: Server Crash on Update with joins +# +CREATE TABLE `t1` ( +`name` varchar(255) NOT NULL, +`value` varchar(4095) DEFAULT NULL, +PRIMARY KEY (`name`) +); +UPDATE `t1` SET value = CONCAT("*.",(SELECT `temptable`.`value` FROM (SELECT * FROM `t1` WHERE `name`="consoleproxy.url.domain") AS `temptable` WHERE `temptable`.`name`="consoleproxy.url.domain")) WHERE `name`="consoleproxy.url.domain"; +drop table t1; +CREATE TABLE `t1` ( +`name` varchar(255) NOT NULL, +`value` varchar(4095) DEFAULT NULL, +PRIMARY KEY (`name`) +); +create table t2 ( +`name` varchar(255) NOT NULL, +`value` varchar(4095) DEFAULT NULL, +PRIMARY KEY (`name`) +); +UPDATE t1 +SET value = (SELECT value FROM t2 WHERE `name`= t1.name) +WHERE value is null ; +drop table t1,t2; +# +#MDEV-8701: Crash on derived query +# +CREATE TABLE t1 ( +data_exit_entry_id int(11) NOT NULL, +data_entry_id int(11) NOT NULL, +data_entry_exit_id int(11) NOT NULL, +data_exit_entry_quantity double NOT NULL +) DEFAULT CHARSET=utf8; +CREATE TABLE t2 ( +data_entry_id int(11) NOT NULL, +data_entry_cost double NOT NULL, +data_entry_quantity double NOT NULL +) DEFAULT CHARSET=utf8; +create algorithm=temptable view v1 as SELECT data_entry_exit_id, data_exit_entry_quantity, data_entry_cost +FROM t1 INNER JOIN t2 as dt ON dt.data_entry_id = t1.data_entry_id; +UPDATE t2 +SET data_entry_cost += ( ( SELECT SUM(data_exit_entry_quantity * data_entry_cost) +FROM +v1 AS query +WHERE data_entry_exit_id = t2.data_entry_id +) +); +UPDATE t2 +SET data_entry_cost += ( ( SELECT SUM(data_exit_entry_quantity * data_entry_cost) +FROM +( SELECT data_entry_exit_id, data_exit_entry_quantity, data_entry_cost +FROM t1 INNER JOIN t2 as dt ON dt.data_entry_id = t1.data_entry_id) AS query +WHERE data_entry_exit_id = t2.data_entry_id +) +); +drop view v1; +drop table t1, t2; diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test index be97dd02dc7..e9d7ff243dd 100644 --- a/mysql-test/t/update.test +++ b/mysql-test/t/update.test @@ -559,3 +559,76 @@ SHOW STATUS LIKE 'HANDLER_UPDATE'; ROLLBACK; DROP TABLE t1, t2; +--echo # +--echo # MDEV-8938: Server Crash on Update with joins +--echo # + +CREATE TABLE `t1` ( + `name` varchar(255) NOT NULL, + `value` varchar(4095) DEFAULT NULL, + PRIMARY KEY (`name`) +); + +UPDATE `t1` SET value = CONCAT("*.",(SELECT `temptable`.`value` FROM (SELECT * FROM `t1` WHERE `name`="consoleproxy.url.domain") AS `temptable` WHERE `temptable`.`name`="consoleproxy.url.domain")) WHERE `name`="consoleproxy.url.domain"; + +drop table t1; + +CREATE TABLE `t1` ( + `name` varchar(255) NOT NULL, + `value` varchar(4095) DEFAULT NULL, + PRIMARY KEY (`name`) +); + +create table t2 ( + `name` varchar(255) NOT NULL, + `value` varchar(4095) DEFAULT NULL, + PRIMARY KEY (`name`) +); + +UPDATE t1 +SET value = (SELECT value FROM t2 WHERE `name`= t1.name) +WHERE value is null ; + +drop table t1,t2; + +--echo # +--echo #MDEV-8701: Crash on derived query +--echo # + +CREATE TABLE t1 ( + data_exit_entry_id int(11) NOT NULL, + data_entry_id int(11) NOT NULL, + data_entry_exit_id int(11) NOT NULL, + data_exit_entry_quantity double NOT NULL +) DEFAULT CHARSET=utf8; + +CREATE TABLE t2 ( + data_entry_id int(11) NOT NULL, + data_entry_cost double NOT NULL, + data_entry_quantity double NOT NULL +) DEFAULT CHARSET=utf8; + +create algorithm=temptable view v1 as SELECT data_entry_exit_id, data_exit_entry_quantity, data_entry_cost + FROM t1 INNER JOIN t2 as dt ON dt.data_entry_id = t1.data_entry_id; + +UPDATE t2 +SET data_entry_cost + = ( ( SELECT SUM(data_exit_entry_quantity * data_entry_cost) + FROM + v1 AS query + WHERE data_entry_exit_id = t2.data_entry_id + ) + ); + +UPDATE t2 +SET data_entry_cost + = ( ( SELECT SUM(data_exit_entry_quantity * data_entry_cost) + FROM + ( SELECT data_entry_exit_id, data_exit_entry_quantity, data_entry_cost + FROM t1 INNER JOIN t2 as dt ON dt.data_entry_id = t1.data_entry_id) AS query + WHERE data_entry_exit_id = t2.data_entry_id + ) + ); + +drop view v1; +drop table t1, t2; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 4fcc007d104..c61c9101a36 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1408,7 +1408,8 @@ static int mysql_test_update(Prepared_statement *stmt, (SELECT_ACL & ~table_list->table->grant.privilege); table_list->register_want_access(SELECT_ACL); #endif - if (setup_fields(thd, 0, stmt->lex->value_list, MARK_COLUMNS_NONE, 0, 0)) + if (setup_fields(thd, 0, stmt->lex->value_list, MARK_COLUMNS_NONE, 0, 0) || + check_unique_table(thd, table_list)) goto error; /* TODO: here we should send types of placeholders to the client. */ DBUG_RETURN(0); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 23e17b0a3bb..c8a7990c23e 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -367,6 +367,9 @@ int mysql_update(THD *thd, DBUG_RETURN(1); /* purecov: inspected */ } + if (check_unique_table(thd, table_list)) + DBUG_RETURN(TRUE); + /* Apply the IN=>EXISTS transformation to all subqueries and optimize them. */ if (select_lex->optimize_unflattened_subqueries(false)) DBUG_RETURN(TRUE); @@ -1036,19 +1039,30 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, setup_ftfuncs(select_lex)) DBUG_RETURN(TRUE); - /* Check that we are not using table that we are updating in a sub select */ - { - TABLE_LIST *duplicate; - if ((duplicate= unique_table(thd, table_list, table_list->next_global, 0))) - { - update_non_unique_table_error(table_list, "UPDATE", duplicate); - DBUG_RETURN(TRUE); - } - } select_lex->fix_prepare_information(thd, conds, &fake_conds); DBUG_RETURN(FALSE); } +/** + Check that we are not using table that we are updating in a sub select + + @param thd Thread handle + @param table_list List of table with first to check + + @retval TRUE Error + @retval FALSE OK +*/ +bool check_unique_table(THD *thd, TABLE_LIST *table_list) +{ + TABLE_LIST *duplicate; + DBUG_ENTER("check_unique_table"); + if ((duplicate= unique_table(thd, table_list, table_list->next_global, 0))) + { + update_non_unique_table_error(table_list, "UPDATE", duplicate); + DBUG_RETURN(TRUE); + } + DBUG_RETURN(FALSE); +} /*************************************************************************** Update multiple tables from join diff --git a/sql/sql_update.h b/sql/sql_update.h index 64029c5d634..4c6f89d8468 100644 --- a/sql/sql_update.h +++ b/sql/sql_update.h @@ -27,6 +27,7 @@ typedef class st_select_lex_unit SELECT_LEX_UNIT; bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, Item **conds, uint order_num, ORDER *order); +bool check_unique_table(THD *thd, TABLE_LIST *table_list); int mysql_update(THD *thd,TABLE_LIST *tables,List &fields, List &values,COND *conds, uint order_num, ORDER *order, ha_rows limit, From 5d754fce95fa378027d1b575d049ab6b78823bb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Mon, 9 Nov 2015 09:23:32 +0200 Subject: [PATCH 49/67] MDEV-8854: New warning messages are unreadable Improved warning messages by quote marks. --- .../suite/innodb/r/innodb-fk-warnings.result | 24 ++-- mysql-test/suite/innodb/r/innodb-fk.result | 6 +- storage/innobase/dict/dict0dict.c | 122 +++++++++--------- storage/xtradb/dict/dict0dict.c | 122 +++++++++--------- 4 files changed, 136 insertions(+), 138 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb-fk-warnings.result b/mysql-test/suite/innodb/r/innodb-fk-warnings.result index 542fc972880..b3360d038df 100644 --- a/mysql-test/suite/innodb/r/innodb-fk-warnings.result +++ b/mysql-test/suite/innodb/r/innodb-fk-warnings.result @@ -24,7 +24,7 @@ create table t2(a int, constraint a foreign key a (a) references t1(a)) engine=i ERROR HY000: Can't create table 'test.t2' (errno: 150) show warnings; Level Code Message -Warning 150 Create table '`test`.`t2`' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns. Error close to foreign key a (a) references t1(a)) engine=innodb. +Warning 150 Create table '`test`.`t2`' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns near ' foreign key a (a) references t1(a)) engine=innodb'. Error 1005 Can't create table 'test.t2' (errno: 150) drop table t1; create table t1(a int not null primary key, b int) engine=innodb; @@ -33,14 +33,14 @@ constraint a foreign key a (a) references t1(b)) engine=innodb; ERROR HY000: Can't create table 'test.t2' (errno: 150) show warnings; Level Code Message -Warning 150 Create table '`test`.`t2`' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns. Error close to foreign key a (a) references t1(b)) engine=innodb. +Warning 150 Create table '`test`.`t2`' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns near ' foreign key a (a) references t1(b)) engine=innodb'. Error 1005 Can't create table 'test.t2' (errno: 150) create table t2(a int, b int, constraint a foreign key a (a) references t1(a)) engine=innodb; alter table t2 add constraint b foreign key (b) references t2(b); ERROR HY000: Can't create table '#sql-temporary' (errno: 150) show warnings; Level Code Message -Warning 150 Alter table '`test`.`t2`' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns. Error close to foreign key (b) references t2(b). +Warning 150 Alter table '`test`.`t2`' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns near ' foreign key (b) references t2(b)'. Error 1005 Can't create table '#sql-temporary' (errno: 150) drop table t2, t1; create table t1 (f1 integer primary key) engine=innodb; @@ -48,7 +48,7 @@ alter table t1 add constraint c1 foreign key (f1) references t11(f1); ERROR HY000: Can't create table '#sql-temporary' (errno: 150) show warnings; Level Code Message -Warning 150 Alter table `test`.`t1` with foreign key constraint failed. Referenced table `test`.`t11` not found in the data dictionary close to foreign key (f1) references t11(f1). +Warning 150 Alter table `test`.`t1` with foreign key constraint failed. Referenced table `test`.`t11` not found in the data dictionary near ' foreign key (f1) references t11(f1)'. Error 1005 Can't create table '#sql-temporary' (errno: 150) drop table t1; create temporary table t1(a int not null primary key, b int, key(b)) engine=innodb; @@ -56,13 +56,13 @@ create temporary table t2(a int, foreign key(a) references t1(a)) engine=innodb; ERROR HY000: Can't create table 'test.t2' (errno: 150) show warnings; Level Code Message -Warning 150 Create table `mysqld.1`.`t2` with foreign key constraint failed. Referenced table `mysqld.1`.`t1` not found in the data dictionary close to foreign key(a) references t1(a)) engine=innodb. +Warning 150 Create table `mysqld.1`.`t2` with foreign key constraint failed. Referenced table `mysqld.1`.`t1` not found in the data dictionary near 'foreign key(a) references t1(a)) engine=innodb'. Error 1005 Can't create table 'test.t2' (errno: 150) alter table t1 add foreign key(b) references t1(a); ERROR HY000: Can't create table '#sql-temporary' (errno: 150) show warnings; Level Code Message -Warning 150 Alter table `mysqld.1`.`t1` with foreign key constraint failed. Referenced table `mysqld.1`.`t1` not found in the data dictionary close to foreign key(b) references t1(a). +Warning 150 Alter table `mysqld.1`.`t1` with foreign key constraint failed. Referenced table `mysqld.1`.`t1` not found in the data dictionary near 'foreign key(b) references t1(a)'. Error 1005 Can't create table '#sql-temporary' (errno: 150) drop table t1; create table t1(a int not null primary key, b int, key(b)) engine=innodb; @@ -70,7 +70,8 @@ alter table t1 add foreign key(a,b) references t1(a); ERROR HY000: Can't create table '#sql-temporary' (errno: 150) show warnings; Level Code Message -Warning 150 Alter table `test`.`t1` with foreign key constraint failed. Foreign key constraint parse error in foreign key(a,b) references t1(a) close to ). Too few referenced columns, you have 1 when you should have 2. +Warning 150 Alter table `test`.`t1` with foreign key constraint failed. Parse error in 'foreign key(a,b) references t1(a)' near ')'. Referencing column count 1 does not match referenced column count 2. + Error 1005 Can't create table '#sql-temporary' (errno: 150) drop table t1; create table t1(a int not null primary key, b int, key(b)) engine=innodb; @@ -78,7 +79,8 @@ alter table t1 add foreign key(a) references t1(a,b); ERROR HY000: Can't create table '#sql-temporary' (errno: 150) show warnings; Level Code Message -Warning 150 Alter table `test`.`t1` with foreign key constraint failed. Foreign key constraint parse error in foreign key(a) references t1(a,b) close to ). Too few referenced columns, you have 2 when you should have 1. +Warning 150 Alter table `test`.`t1` with foreign key constraint failed. Parse error in 'foreign key(a) references t1(a,b)' near ')'. Referencing column count 2 does not match referenced column count 1. + Error 1005 Can't create table '#sql-temporary' (errno: 150) drop table t1; create table t1 (f1 integer not null primary key) engine=innodb; @@ -86,13 +88,13 @@ alter table t1 add constraint c1 foreign key (f1) references t1(f1) on update se ERROR HY000: Can't create table '#sql-temporary' (errno: 150) show warnings; Level Code Message -Warning 150 Alter table `test`.`t1` with foreign key constraint failed. You have defined a SET NULL condition but column f1 is defined as NOT NULL in foreign key (f1) references t1(f1) on update set null close to on update set null. +Warning 150 Alter table `test`.`t1` with foreign key constraint failed. You have defined a SET NULL condition but column 'f1' is defined as NOT NULL in ' foreign key (f1) references t1(f1) on update set null' near ' on update set null'. Error 1005 Can't create table '#sql-temporary' (errno: 150) create table t2(a int not null, foreign key(a) references t1(f1) on delete set null) engine=innodb; ERROR HY000: Can't create table 'test.t2' (errno: 150) show warnings; Level Code Message -Warning 150 Create table `test`.`t2` with foreign key constraint failed. You have defined a SET NULL condition but column a is defined as NOT NULL in foreign key(a) references t1(f1) on delete set null) engine=innodb close to on delete set null) engine=innodb. +Warning 150 Create table `test`.`t2` with foreign key constraint failed. You have defined a SET NULL condition but column 'a' is defined as NOT NULL in 'foreign key(a) references t1(f1) on delete set null) engine=innodb' near ' on delete set null) engine=innodb'. Error 1005 Can't create table 'test.t2' (errno: 150) drop table t1; create table t1 (id int not null primary key, f1 int, f2 int, key(f1)) engine=innodb; @@ -100,6 +102,6 @@ create table t2(a char(20), key(a), foreign key(a) references t1(f1)) engine=inn ERROR HY000: Can't create table 'test.t2' (errno: 150) show warnings; Level Code Message -Warning 150 Create table `test`.`t2` with foreign key constraint failed. Field type or character set for column a does not mach referenced column f1 close to foreign key(a) references t1(f1)) engine=innodb +Warning 150 Create table `test`.`t2` with foreign key constraint failed. Field type or character set for column 'a' does not mach referenced column 'f1' near 'foreign key(a) references t1(f1)) engine=innodb'. Error 1005 Can't create table 'test.t2' (errno: 150) drop table t1; diff --git a/mysql-test/suite/innodb/r/innodb-fk.result b/mysql-test/suite/innodb/r/innodb-fk.result index 2b53bc21b31..6c3306f5c15 100644 --- a/mysql-test/suite/innodb/r/innodb-fk.result +++ b/mysql-test/suite/innodb/r/innodb-fk.result @@ -50,8 +50,8 @@ CONSTRAINT fk3 FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE ERROR HY000: Can't create table 'test.t2' (errno: 150) show warnings; Level Code Message -Warning 150 Create table `test`.`t2` with foreign key constraint failed. Referenced table `test`.`t3` not found in the data dictionary close to FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE -) ENGINE=InnoDB. +Warning 150 Create table `test`.`t2` with foreign key constraint failed. Referenced table `test`.`t3` not found in the data dictionary near ' FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE +) ENGINE=InnoDB'. Error 1005 Can't create table 'test.t2' (errno: 150) CREATE TABLE t2 ( id int(11) NOT NULL AUTO_INCREMENT, @@ -64,7 +64,7 @@ ALTER TABLE t2 ADD CONSTRAINT fk3 FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE ERROR HY000: Can't create table '#sql-temporary' (errno: 150) show warnings; Level Code Message -Warning 150 Alter table `test`.`t2` with foreign key constraint failed. Referenced table `test`.`t3` not found in the data dictionary close to FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE. +Warning 150 Alter table `test`.`t2` with foreign key constraint failed. Referenced table `test`.`t3` not found in the data dictionary near ' FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE'. Error 1005 Can't create table '#sql-temporary' (errno: 150) drop table t2; drop table t1; diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c index ad900385325..17e9eb122df 100644 --- a/storage/innobase/dict/dict0dict.c +++ b/storage/innobase/dict/dict0dict.c @@ -3628,13 +3628,13 @@ dict_foreign_push_index_error( "%s table '%s' with foreign key constraint" " failed. There is no index in the referenced" " table where the referenced columns appear" - " as the first columns. Error close to %s.\n", + " as the first columns near '%s'.\n", operation, create_name, latest_foreign); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table '%s' with foreign key constraint" " failed. There is no index in the referenced" " table where the referenced columns appear" - " as the first columns. Error close to %s.", + " as the first columns near '%s'.", operation, create_name, latest_foreign); break; } @@ -3643,13 +3643,13 @@ dict_foreign_push_index_error( "%s table '%s' with foreign key constraint" " failed. There is only prefix index in the referenced" " table where the referenced columns appear" - " as the first columns. Error close to %s.\n", + " as the first columns near '%s'.\n", operation, create_name, latest_foreign); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table '%s' with foreign key constraint" " failed. There is only prefix index in the referenced" " table where the referenced columns appear" - " as the first columns. Error close to %s.", + " as the first columns near '%s'.", operation, create_name, latest_foreign); break; } @@ -3657,12 +3657,12 @@ dict_foreign_push_index_error( fprintf(ef, "%s table %s with foreign key constraint" " failed. You have defined a SET NULL condition but " - "field %s on index is defined as NOT NULL close to %s\n", + "column '%s' on index is defined as NOT NULL near '%s'.\n", operation, create_name, columns[err_col], latest_foreign); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" " failed. You have defined a SET NULL condition but " - "field %s on index is defined as NOT NULL close to %s", + "column '%s' on index is defined as NOT NULL near '%s'.", operation, create_name, columns[err_col], latest_foreign); break; } @@ -3675,13 +3675,13 @@ dict_foreign_push_index_error( table, dict_col_get_no(field->col)); fprintf(ef, "%s table %s with foreign key constraint" - " failed. Field type or character set for column %s " - "does not mach referenced column %s close to %s\n", + " failed. Field type or character set for column '%s' " + "does not mach referenced column '%s' near '%s'.\n", operation, create_name, columns[err_col], col_name, latest_foreign); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. Field type or character set for column %s " - "does not mach referenced column %s close to %s", + " failed. Field type or character set for column '%s' " + "does not mach referenced column '%s' near '%s'.", operation, create_name, columns[err_col], col_name, latest_foreign); break; } @@ -3973,14 +3973,14 @@ loop: if (!success) { dict_foreign_report_syntax_err( "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.\n", + " failed. Parse error in '%s'" + " near '%s'.\n", operation, create_name, start_of_latest_foreign, orig); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.", + " failed. Parse error in '%s'" + " near '%s'.", operation, create_name, start_of_latest_foreign, orig); return(DB_CANNOT_ADD_CONSTRAINT); @@ -4009,16 +4009,16 @@ col_loop1: dict_foreign_error_report_low(ef, create_name); fprintf(ef, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.\n", + " failed. Parse error in '%s'" + " near '%s'.\n", operation, create_name, start_of_latest_foreign, orig); mutex_exit(&dict_foreign_err_mutex); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.", + " failed. Parse error in '%s'" + " near '%s'.", operation, create_name, start_of_latest_foreign, orig); return(DB_CANNOT_ADD_CONSTRAINT); @@ -4038,14 +4038,14 @@ col_loop1: if (!success) { dict_foreign_report_syntax_err( "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.\n", + " failed. Parse error in '%s'" + " near '%s'.\n", operation, create_name, start_of_latest_foreign, orig); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.", + " failed. Parse error in '%s'" + " near '%s'.", operation, create_name, start_of_latest_foreign, orig); return(DB_CANNOT_ADD_CONSTRAINT); @@ -4081,14 +4081,14 @@ col_loop1: if (!success || !my_isspace(cs, *ptr)) { dict_foreign_report_syntax_err( "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.\n", + " failed. Parse error in '%s'" + " near '%s'.\n", operation, create_name, start_of_latest_foreign, orig); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.", + " failed. Parse error in '%s'" + " near '%s'.", operation, create_name, start_of_latest_foreign, orig); return(DB_CANNOT_ADD_CONSTRAINT); } @@ -4148,7 +4148,7 @@ col_loop1: ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint failed. Referenced table %s not found in the data dictionary " - "close to %s.", + "near '%s'.", operation, create_name, buf, start_of_latest_foreign); dict_foreign_free(foreign); @@ -4157,7 +4157,7 @@ col_loop1: dict_foreign_error_report_low(ef, create_name); fprintf(ef, "%s table %s with foreign key constraint failed. Referenced table %s not found in the data dictionary " - "close to %s.\n", + "near '%s'.\n", operation, create_name, buf, start_of_latest_foreign); mutex_exit(&dict_foreign_err_mutex); @@ -4172,14 +4172,14 @@ col_loop1: dict_foreign_free(foreign); dict_foreign_report_syntax_err( "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.\n", + " failed. Parse error in '%s'" + " near '%s'.\n", operation, create_name, start_of_latest_foreign, orig); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.", + " failed. Parse error in '%s'" + " near '%s'.", operation, create_name, start_of_latest_foreign, orig); return(DB_CANNOT_ADD_CONSTRAINT); @@ -4201,16 +4201,16 @@ col_loop2: dict_foreign_error_report_low(ef, create_name); fprintf(ef, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.\n", + " failed. Parse error in '%s'" + " near '%s'.\n", operation, create_name, start_of_latest_foreign, orig); mutex_exit(&dict_foreign_err_mutex); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.", + " failed. Parse error in '%s'" + " near '%s'.", operation, create_name, start_of_latest_foreign, orig); return(DB_CANNOT_ADD_CONSTRAINT); } @@ -4228,14 +4228,12 @@ col_loop2: dict_foreign_report_syntax_err( "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s. Too few referenced columns.\n", + " failed. Parse error in '%s' near '%s'. Referencing column count does not match referenced column count.\n", operation, create_name, start_of_latest_foreign, orig); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s. Too few referenced columns, you have %d when you should have %d.", + " failed. Parse error in '%s' near '%s'. Referencing column count %d does not match referenced column count %d.\n", operation, create_name, start_of_latest_foreign, orig, i, foreign->n_fields); dict_foreign_free(foreign); @@ -4268,14 +4266,14 @@ scan_on_conditions: dict_foreign_report_syntax_err( "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.\n", + " failed. Parse error in '%s'" + " near '%s'.\n", operation, create_name, start_of_latest_foreign, start_of_latest_set); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.", + " failed. Parse error in '%s'" + " near '%s'.", operation, create_name, start_of_latest_foreign, start_of_latest_set); return(DB_CANNOT_ADD_CONSTRAINT); @@ -4316,14 +4314,14 @@ scan_on_conditions: dict_foreign_free(foreign); dict_foreign_report_syntax_err( "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.\n", + " failed. Parse error in '%s'" + " near '%s'.\n", operation, create_name, start_of_latest_foreign, start_of_latest_set); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.", + " failed. Parse error in '%s'" + " near '%s'.", operation, create_name, start_of_latest_foreign, start_of_latest_set); return(DB_CANNOT_ADD_CONSTRAINT); @@ -4345,14 +4343,14 @@ scan_on_conditions: dict_foreign_free(foreign); dict_foreign_report_syntax_err( "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.\n", + " failed. Parse error in '%s'" + " near '%s'.\n", operation, create_name, start_of_latest_foreign, start_of_latest_set); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.", + " failed. Parse error in '%s'" + " near '%s'.", operation, create_name, start_of_latest_foreign, start_of_latest_set); return(DB_CANNOT_ADD_CONSTRAINT); @@ -4365,14 +4363,14 @@ scan_on_conditions: dict_foreign_free(foreign); dict_foreign_report_syntax_err( "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.\n", + " failed. Parse error in '%s'" + " near '%s'.\n", operation, create_name, start_of_latest_foreign, start_of_latest_set); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.", + " failed. Parse error in '%s'" + " near '%s'.", operation, create_name, start_of_latest_foreign, start_of_latest_set); return(DB_CANNOT_ADD_CONSTRAINT); } @@ -4392,16 +4390,16 @@ scan_on_conditions: dict_foreign_error_report_low(ef, create_name); fprintf(ef, "%s table %s with foreign key constraint" - " failed. You have defined a SET NULL condition but column %s is defined as NOT NULL" - " in %s close to %s.\n", + " failed. You have defined a SET NULL condition but column '%s' is defined as NOT NULL" + " in '%s' near '%s'.\n", operation, create_name, col_name, start_of_latest_foreign, start_of_latest_set); mutex_exit(&dict_foreign_err_mutex); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. You have defined a SET NULL condition but column %s is defined as NOT NULL" - " in %s close to %s.", + " failed. You have defined a SET NULL condition but column '%s' is defined as NOT NULL" + " in '%s' near '%s'.", operation, create_name, col_name, start_of_latest_foreign, start_of_latest_set); dict_foreign_free(foreign); @@ -4427,14 +4425,14 @@ try_find_index: fprintf(ef, "%s table %s with foreign key constraint" " failed. You have more than one on delete or on update clause" - " in %s close to %s.\n", + " in '%s' near '%s'.\n", operation, create_name, start_of_latest_foreign, start_of_latest_set); mutex_exit(&dict_foreign_err_mutex); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" " failed. You have more than one on delete or on update clause" - " in %s close to %s.", + " in '%s' near '%s'.", operation, create_name, start_of_latest_foreign, start_of_latest_set); dict_foreign_free(foreign); return(DB_CANNOT_ADD_CONSTRAINT); diff --git a/storage/xtradb/dict/dict0dict.c b/storage/xtradb/dict/dict0dict.c index cd8e4159033..7351de5de2b 100644 --- a/storage/xtradb/dict/dict0dict.c +++ b/storage/xtradb/dict/dict0dict.c @@ -3762,13 +3762,13 @@ dict_foreign_push_index_error( "%s table '%s' with foreign key constraint" " failed. There is no index in the referenced" " table where the referenced columns appear" - " as the first columns. Error close to %s.\n", + " as the first columns near '%s'.\n", operation, create_name, latest_foreign); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table '%s' with foreign key constraint" " failed. There is no index in the referenced" " table where the referenced columns appear" - " as the first columns. Error close to %s.", + " as the first columns near '%s'.", operation, create_name, latest_foreign); break; } @@ -3777,13 +3777,13 @@ dict_foreign_push_index_error( "%s table '%s' with foreign key constraint" " failed. There is only prefix index in the referenced" " table where the referenced columns appear" - " as the first columns. Error close to %s.\n", + " as the first columns near '%s'.\n", operation, create_name, latest_foreign); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table '%s' with foreign key constraint" " failed. There is only prefix index in the referenced" " table where the referenced columns appear" - " as the first columns. Error close to %s.", + " as the first columns near '%s'.", operation, create_name, latest_foreign); break; } @@ -3791,12 +3791,12 @@ dict_foreign_push_index_error( fprintf(ef, "%s table %s with foreign key constraint" " failed. You have defined a SET NULL condition but " - "field %s on index is defined as NOT NULL close to %s\n", + "column '%s' on index is defined as NOT NULL near '%s'.\n", operation, create_name, columns[err_col], latest_foreign); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" " failed. You have defined a SET NULL condition but " - "field %s on index is defined as NOT NULL close to %s", + "column '%s' on index is defined as NOT NULL near '%s'.", operation, create_name, columns[err_col], latest_foreign); break; } @@ -3809,13 +3809,13 @@ dict_foreign_push_index_error( table, dict_col_get_no(field->col)); fprintf(ef, "%s table %s with foreign key constraint" - " failed. Field type or character set for column %s " - "does not mach referenced column %s close to %s\n", + " failed. Field type or character set for column '%s' " + "does not mach referenced column '%s' near '%s'.\n", operation, create_name, columns[err_col], col_name, latest_foreign); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. Field type or character set for column %s " - "does not mach referenced column %s close to %s", + " failed. Field type or character set for column '%s' " + "does not mach referenced column '%s' near '%s'.", operation, create_name, columns[err_col], col_name, latest_foreign); break; } @@ -4107,14 +4107,14 @@ loop: if (!success) { dict_foreign_report_syntax_err( "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.\n", + " failed. Parse error in '%s'" + " near '%s'.\n", operation, create_name, start_of_latest_foreign, orig); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.", + " failed. Parse error in '%s'" + " near '%s'.", operation, create_name, start_of_latest_foreign, orig); return(DB_CANNOT_ADD_CONSTRAINT); @@ -4143,16 +4143,16 @@ col_loop1: dict_foreign_error_report_low(ef, create_name); fprintf(ef, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.\n", + " failed. Parse error in '%s'" + " near '%s'.\n", operation, create_name, start_of_latest_foreign, orig); mutex_exit(&dict_foreign_err_mutex); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.", + " failed. Parse error in '%s'" + " near '%s'.", operation, create_name, start_of_latest_foreign, orig); return(DB_CANNOT_ADD_CONSTRAINT); @@ -4172,14 +4172,14 @@ col_loop1: if (!success) { dict_foreign_report_syntax_err( "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.\n", + " failed. Parse error in '%s'" + " near '%s'.\n", operation, create_name, start_of_latest_foreign, orig); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.", + " failed. Parse error in '%s'" + " near '%s'.", operation, create_name, start_of_latest_foreign, orig); return(DB_CANNOT_ADD_CONSTRAINT); @@ -4215,14 +4215,14 @@ col_loop1: if (!success || !my_isspace(cs, *ptr)) { dict_foreign_report_syntax_err( "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.\n", + " failed. Parse error in '%s'" + " near '%s'.\n", operation, create_name, start_of_latest_foreign, orig); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.", + " failed. Parse error in '%s'" + " near '%s'.", operation, create_name, start_of_latest_foreign, orig); return(DB_CANNOT_ADD_CONSTRAINT); } @@ -4282,7 +4282,7 @@ col_loop1: ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint failed. Referenced table %s not found in the data dictionary " - "close to %s.", + "near '%s'.", operation, create_name, buf, start_of_latest_foreign); dict_foreign_free(foreign); @@ -4291,7 +4291,7 @@ col_loop1: dict_foreign_error_report_low(ef, create_name); fprintf(ef, "%s table %s with foreign key constraint failed. Referenced table %s not found in the data dictionary " - "close to %s.\n", + "near '%s'.\n", operation, create_name, buf, start_of_latest_foreign); mutex_exit(&dict_foreign_err_mutex); @@ -4306,14 +4306,14 @@ col_loop1: dict_foreign_free(foreign); dict_foreign_report_syntax_err( "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.\n", + " failed. Parse error in '%s'" + " near '%s'.\n", operation, create_name, start_of_latest_foreign, orig); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.", + " failed. Parse error in '%s'" + " near '%s'.", operation, create_name, start_of_latest_foreign, orig); return(DB_CANNOT_ADD_CONSTRAINT); @@ -4335,16 +4335,16 @@ col_loop2: dict_foreign_error_report_low(ef, create_name); fprintf(ef, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.\n", + " failed. Parse error in '%s'" + " near '%s'.\n", operation, create_name, start_of_latest_foreign, orig); mutex_exit(&dict_foreign_err_mutex); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.", + " failed. Parse error in '%s'" + " near '%s'.", operation, create_name, start_of_latest_foreign, orig); return(DB_CANNOT_ADD_CONSTRAINT); } @@ -4362,14 +4362,12 @@ col_loop2: dict_foreign_report_syntax_err( "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s. Too few referenced columns\n", + " failed. Parse error in '%s' near '%s'. Referencing column count does not match referenced column count.\n", operation, create_name, start_of_latest_foreign, orig); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s. Too few referenced columns, you have %d when you should have %d.", + " failed. Parse error in '%s' near '%s'. Referencing column count %d does not match referenced column count %d.\n", operation, create_name, start_of_latest_foreign, orig, i, foreign->n_fields); dict_foreign_free(foreign); @@ -4402,14 +4400,14 @@ scan_on_conditions: dict_foreign_report_syntax_err( "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.\n", + " failed. Parse error in '%s'" + " near '%s'.\n", operation, create_name, start_of_latest_foreign, start_of_latest_set); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.", + " failed. Parse error in '%s'" + " near '%s'.", operation, create_name, start_of_latest_foreign, start_of_latest_set); return(DB_CANNOT_ADD_CONSTRAINT); @@ -4450,14 +4448,14 @@ scan_on_conditions: dict_foreign_free(foreign); dict_foreign_report_syntax_err( "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.\n", + " failed. Parse error in '%s'" + " near '%s'.\n", operation, create_name, start_of_latest_foreign, start_of_latest_set); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.", + " failed. Parse error in '%s'" + " near '%s'.", operation, create_name, start_of_latest_foreign, start_of_latest_set); return(DB_CANNOT_ADD_CONSTRAINT); @@ -4479,14 +4477,14 @@ scan_on_conditions: dict_foreign_free(foreign); dict_foreign_report_syntax_err( "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.\n", + " failed. Parse error in '%s'" + " near '%s'.\n", operation, create_name, start_of_latest_foreign, start_of_latest_set); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.", + " failed. Parse error in '%s'" + " near '%s'.", operation, create_name, start_of_latest_foreign, start_of_latest_set); return(DB_CANNOT_ADD_CONSTRAINT); @@ -4499,14 +4497,14 @@ scan_on_conditions: dict_foreign_free(foreign); dict_foreign_report_syntax_err( "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.\n", + " failed. Parse error in '%s'" + " near '%s'.\n", operation, create_name, start_of_latest_foreign, start_of_latest_set); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. Foreign key constraint parse error in %s" - " close to %s.", + " failed. Parse error in '%s'" + " near '%s'.", operation, create_name, start_of_latest_foreign, start_of_latest_set); return(DB_CANNOT_ADD_CONSTRAINT); } @@ -4526,16 +4524,16 @@ scan_on_conditions: dict_foreign_error_report_low(ef, create_name); fprintf(ef, "%s table %s with foreign key constraint" - " failed. You have defined a SET NULL condition but column %s is defined as NOT NULL" - " in %s close to %s.\n", + " failed. You have defined a SET NULL condition but column '%s' is defined as NOT NULL" + " in '%s' near '%s'.\n", operation, create_name, col_name, start_of_latest_foreign, start_of_latest_set); mutex_exit(&dict_foreign_err_mutex); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" - " failed. You have defined a SET NULL condition but column %s is defined as NOT NULL" - " in %s close to %s.", + " failed. You have defined a SET NULL condition but column '%s' is defined as NOT NULL" + " in '%s' near '%s'.", operation, create_name, col_name, start_of_latest_foreign, start_of_latest_set); dict_foreign_free(foreign); @@ -4561,14 +4559,14 @@ try_find_index: fprintf(ef, "%s table %s with foreign key constraint" " failed. You have more than one on delete or on update clause" - " in %s close to %s.\n", + " in '%s' near '%s'.\n", operation, create_name, start_of_latest_foreign, start_of_latest_set); mutex_exit(&dict_foreign_err_mutex); ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT, "%s table %s with foreign key constraint" " failed. You have more than one on delete or on update clause" - " in %s close to %s.", + " in '%s' near '%s'.", operation, create_name, start_of_latest_foreign, start_of_latest_set); dict_foreign_free(foreign); return(DB_CANNOT_ADD_CONSTRAINT); From 1694d813997198e86f6a8aa6aefffb687c9992dd Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Mon, 9 Nov 2015 12:29:26 +0100 Subject: [PATCH 50/67] MDEV-8533 Debug embedded server does not build on Windows pre/CMakeLists.txt defines CMAKE_DEBUG_POSTFIX which causes a different library name on Windows debug build (pcred.lib rather than pre.lib) However MERGE_LIBRARIES macro that is used to create static embedded library (out of other static libraries), can not handle per-configuration library names. Thus the build fails with "pre.lib not found" Fix is to remove unnecessary CMAKE_DEBUG_POSTFIX --- pcre/CMakeLists.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pcre/CMakeLists.txt b/pcre/CMakeLists.txt index 90ebc0d5100..a4faef6f47a 100644 --- a/pcre/CMakeLists.txt +++ b/pcre/CMakeLists.txt @@ -311,11 +311,6 @@ IF(MSVC) ENDIF(MSVC) SET(CMAKE_INCLUDE_CURRENT_DIR 1) -# needed to make sure to not link debug libs -# against release libs and vice versa -IF(WIN32) - SET(CMAKE_DEBUG_POSTFIX "d") -ENDIF(WIN32) SET(targets) From 9f862ce026c9102695f01aaa3090d5e99ffd80a1 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Mon, 9 Nov 2015 17:58:35 +0300 Subject: [PATCH 51/67] MDEV#7383: engine-independent-stats column_stats has limited values for max/min values Patch from Daniel Black: - Change the charset of mysql.column_stats.{min_value, max_value} from utf8_bin varchar to varbinary - Adjust the code that saves/reads the data accordingly. - Also provide upgrade statement in mysql_system_tables_fix.sql --- mysql-test/r/statistics.result | 19 +++++++++++++++++++ mysql-test/t/statistics.test | 16 ++++++++++++++++ scripts/mysql_system_tables.sql | 2 +- scripts/mysql_system_tables_fix.sql | 2 ++ sql/sql_statistics.cc | 16 ++++++++-------- 5 files changed, 46 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/statistics.result b/mysql-test/r/statistics.result index a2d3d392f45..bd6a0849e3d 100644 --- a/mysql-test/r/statistics.result +++ b/mysql-test/r/statistics.result @@ -1622,3 +1622,22 @@ test t2 id 1 1024 0.0000 8.0000 63 SINGLE_PREC_HB 03070B0F13171B1F23272B2F33373B set histogram_size=default; drop table t1, t2; set use_stat_tables=@save_use_stat_tables; +# +# Bug MDEV-7383: min/max value for a column not utf8 compatible +# +create table t1 (a varchar(100)) engine=MyISAM; +insert into t1 values(unhex('D879626AF872675F73E662F8')); +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +show warnings; +Level Code Message +select db_name, table_name, column_name, +HEX(min_value), HEX(max_value), +nulls_ratio, avg_frequency, +hist_size, hist_type, HEX(histogram) +FROM mysql.column_stats; +db_name table_name column_name HEX(min_value) HEX(max_value) nulls_ratio avg_frequency hist_size hist_type HEX(histogram) +test t1 a D879626AF872675F73E662F8 D879626AF872675F73E662F8 0.0000 1.0000 0 NULL NULL +drop table t1; diff --git a/mysql-test/t/statistics.test b/mysql-test/t/statistics.test index 36e2c5a77bd..2c8dec307cc 100644 --- a/mysql-test/t/statistics.test +++ b/mysql-test/t/statistics.test @@ -701,3 +701,19 @@ drop table t1, t2; set use_stat_tables=@save_use_stat_tables; +--echo # +--echo # Bug MDEV-7383: min/max value for a column not utf8 compatible +--echo # + +create table t1 (a varchar(100)) engine=MyISAM; +insert into t1 values(unhex('D879626AF872675F73E662F8')); +analyze table t1 persistent for all; +show warnings; + +select db_name, table_name, column_name, + HEX(min_value), HEX(max_value), + nulls_ratio, avg_frequency, + hist_size, hist_type, HEX(histogram) + FROM mysql.column_stats; + +drop table t1; diff --git a/scripts/mysql_system_tables.sql b/scripts/mysql_system_tables.sql index bc89ae82dbb..14b59bb3411 100644 --- a/scripts/mysql_system_tables.sql +++ b/scripts/mysql_system_tables.sql @@ -220,7 +220,7 @@ set @had_proxies_priv_table= @@warning_count != 0; CREATE TABLE IF NOT EXISTS table_stats (db_name varchar(64) NOT NULL, table_name varchar(64) NOT NULL, cardinality bigint(21) unsigned DEFAULT NULL, PRIMARY KEY (db_name,table_name) ) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Statistics on Tables'; -CREATE TABLE IF NOT EXISTS column_stats (db_name varchar(64) NOT NULL, table_name varchar(64) NOT NULL, column_name varchar(64) NOT NULL, min_value varchar(255) DEFAULT NULL, max_value varchar(255) DEFAULT NULL, nulls_ratio decimal(12,4) DEFAULT NULL, avg_length decimal(12,4) DEFAULT NULL, avg_frequency decimal(12,4) DEFAULT NULL, hist_size tinyint unsigned, hist_type enum('SINGLE_PREC_HB','DOUBLE_PREC_HB'), histogram varbinary(255), PRIMARY KEY (db_name,table_name,column_name) ) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Statistics on Columns'; +CREATE TABLE IF NOT EXISTS column_stats (db_name varchar(64) NOT NULL, table_name varchar(64) NOT NULL, column_name varchar(64) NOT NULL, min_value varbinary(255) DEFAULT NULL, max_value varbinary(255) DEFAULT NULL, nulls_ratio decimal(12,4) DEFAULT NULL, avg_length decimal(12,4) DEFAULT NULL, avg_frequency decimal(12,4) DEFAULT NULL, hist_size tinyint unsigned, hist_type enum('SINGLE_PREC_HB','DOUBLE_PREC_HB'), histogram varbinary(255), PRIMARY KEY (db_name,table_name,column_name) ) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Statistics on Columns'; CREATE TABLE IF NOT EXISTS index_stats (db_name varchar(64) NOT NULL, table_name varchar(64) NOT NULL, index_name varchar(64) NOT NULL, prefix_arity int(11) unsigned NOT NULL, avg_frequency decimal(12,4) DEFAULT NULL, PRIMARY KEY (db_name,table_name,index_name,prefix_arity) ) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Statistics on Indexes'; diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql index 33b4306b103..f034af4f898 100644 --- a/scripts/mysql_system_tables_fix.sql +++ b/scripts/mysql_system_tables_fix.sql @@ -711,3 +711,5 @@ flush privileges; ALTER TABLE help_category MODIFY url TEXT NOT NULL; ALTER TABLE help_topic MODIFY url TEXT NOT NULL; +# MDEV-7383 - varbinary on mix/max of column_stats +alter table column_stats modify min_value varbinary(255) DEFAULT NULL, modify max_value varbinary(255) DEFAULT NULL; diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index 4ce1f3ec22a..c2150ba9309 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -888,7 +888,7 @@ public: @note A value from the field min_value/max_value is always converted - into a utf8 string. If the length of the column 'min_value'/'max_value' + into a varbinary string. If the length of the column 'min_value'/'max_value' is less than the length of the string the string is trimmed to fit the length of the column. */ @@ -896,7 +896,7 @@ public: void store_stat_fields() { char buff[MAX_FIELD_WIDTH]; - String val(buff, sizeof(buff), &my_charset_utf8_bin); + String val(buff, sizeof(buff), &my_charset_bin); for (uint i= COLUMN_STAT_MIN_VALUE; i <= COLUMN_STAT_HISTOGRAM; i++) { @@ -913,7 +913,7 @@ public: else { table_field->collected_stats->min_value->val_str(&val); - stat_field->store(val.ptr(), val.length(), &my_charset_utf8_bin); + stat_field->store(val.ptr(), val.length(), &my_charset_bin); } break; case COLUMN_STAT_MAX_VALUE: @@ -922,7 +922,7 @@ public: else { table_field->collected_stats->max_value->val_str(&val); - stat_field->store(val.ptr(), val.length(), &my_charset_utf8_bin); + stat_field->store(val.ptr(), val.length(), &my_charset_bin); } break; case COLUMN_STAT_NULLS_RATIO: @@ -983,7 +983,7 @@ public: if (find_stat()) { char buff[MAX_FIELD_WIDTH]; - String val(buff, sizeof(buff), &my_charset_utf8_bin); + String val(buff, sizeof(buff), &my_charset_bin); for (uint i= COLUMN_STAT_MIN_VALUE; i <= COLUMN_STAT_HIST_TYPE; i++) { @@ -1002,12 +1002,12 @@ public: case COLUMN_STAT_MIN_VALUE: stat_field->val_str(&val); table_field->read_stats->min_value->store(val.ptr(), val.length(), - &my_charset_utf8_bin); + &my_charset_bin); break; case COLUMN_STAT_MAX_VALUE: stat_field->val_str(&val); table_field->read_stats->max_value->store(val.ptr(), val.length(), - &my_charset_utf8_bin); + &my_charset_bin); break; case COLUMN_STAT_NULLS_RATIO: table_field->read_stats->set_nulls_ratio(stat_field->val_real()); @@ -1053,7 +1053,7 @@ public: if (find_stat()) { char buff[MAX_FIELD_WIDTH]; - String val(buff, sizeof(buff), &my_charset_utf8_bin); + String val(buff, sizeof(buff), &my_charset_bin); uint fldno= COLUMN_STAT_HISTOGRAM; Field *stat_field= stat_table->field[fldno]; table_field->read_stats->set_not_null(fldno); From 7e4da9b370d032db9015adb47ad2ff585aeaea5d Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Fri, 6 Nov 2015 16:36:41 +0100 Subject: [PATCH 52/67] DEV-8632 Segmentation fault on INSERT View/derived fields should be taken into account when we build ref_pointer_array constructed. DBUG_ASSERTs added to avoid memory overrun. --- mysql-test/r/view.result | 33 +++++++++++++++++++++++++++++++++ mysql-test/t/view.test | 35 +++++++++++++++++++++++++++++++++++ sql/item.cc | 3 +++ sql/sql_select.cc | 6 ++++++ sql/sql_view.cc | 5 +++++ sql/sql_yacc.yy | 9 +++++++++ 6 files changed, 91 insertions(+) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 57065d74274..b008e623b5d 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -5479,6 +5479,39 @@ UPDATE t1, t2 SET a = 1 WHERE a IN ( SELECT 0 FROM v3 ); EXECUTE stmt; DROP TABLE t1, t2, t3; DROP VIEW v3; +# +# MDEV-8632: Segmentation fault on INSERT +# +CREATE TABLE `t1` ( +`id` int(10) unsigned NOT NULL, +`r` float NOT NULL, +PRIMARY KEY (`id`) +) DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +create view v1 as select id, if(r=r,1,2) as d from t1; +create view v2 as +select id, +d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d as p +from v1; +insert into t1 (id, r) +select id,p from +( +select id, +d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d as p +from ( +select id, if(r=r,1,2) as d +from t1 +) a +) b +on duplicate key update r=p; +insert into t1 (id, r) +select id,p from v2 +on duplicate key update r=p; +prepare stmt from "insert into t1 (id, r) select id,p from v2 on duplicate key update r=p"; +execute stmt; +execute stmt; +deallocate prepare stmt; +drop view v1,v2; +drop table `t1`; # ----------------------------------------------------------------- # -- End of 5.5 tests. # ----------------------------------------------------------------- diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index fe04cdfecec..815be87b04e 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -5445,6 +5445,41 @@ EXECUTE stmt; DROP TABLE t1, t2, t3; DROP VIEW v3; +--echo # +--echo # MDEV-8632: Segmentation fault on INSERT +--echo # +CREATE TABLE `t1` ( + `id` int(10) unsigned NOT NULL, + `r` float NOT NULL, + PRIMARY KEY (`id`) +) DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +create view v1 as select id, if(r=r,1,2) as d from t1; +create view v2 as + select id, + d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d as p + from v1; +insert into t1 (id, r) +select id,p from +( + select id, + d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d as p + from ( + select id, if(r=r,1,2) as d + from t1 + ) a +) b +on duplicate key update r=p; +insert into t1 (id, r) +select id,p from v2 +on duplicate key update r=p; + +prepare stmt from "insert into t1 (id, r) select id,p from v2 on duplicate key update r=p"; +execute stmt; +execute stmt; +deallocate prepare stmt; + +drop view v1,v2; +drop table `t1`; --echo # ----------------------------------------------------------------- --echo # -- End of 5.5 tests. --echo # ----------------------------------------------------------------- diff --git a/sql/item.cc b/sql/item.cc index 878c9604ca2..840272c57a4 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1891,6 +1891,8 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array, */ Item_aggregate_ref *item_ref; uint el= fields.elements; + DBUG_ASSERT(fields.elements <= + thd->lex->current_select->ref_pointer_array_size); /* If this is an item_ref, get the original item This is a safety measure if this is called for things that is @@ -6719,6 +6721,7 @@ Item *Item_field::update_value_transformer(uchar *select_arg) { List *all_fields= &select->join->all_fields; Item **ref_pointer_array= select->ref_pointer_array; + DBUG_ASSERT(all_fields->elements <= select->ref_pointer_array_size); int el= all_fields->elements; Item_ref *ref; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index e960a3d7c45..ef1b5b0014e 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -427,6 +427,7 @@ fix_inner_refs(THD *thd, List &all_fields, SELECT_LEX *select, if (ref_pointer_array && !ref->found_in_select_list) { int el= all_fields.elements; + DBUG_ASSERT(all_fields.elements <= select->ref_pointer_array_size); ref_pointer_array[el]= item; /* Add the field item to the select list of the current select. */ all_fields.push_front(item); @@ -832,6 +833,7 @@ JOIN::prepare(Item ***rref_pointer_array, { Item_field *field= new Item_field(thd, *(Item_field**)ord->item); int el= all_fields.elements; + DBUG_ASSERT(all_fields.elements <= select_lex->ref_pointer_array_size); ref_pointer_array[el]= field; all_fields.push_front(field); ord->item= ref_pointer_array + el; @@ -20596,6 +20598,8 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, return TRUE; /* Wrong field. */ uint el= all_fields.elements; + DBUG_ASSERT(all_fields.elements <= + thd->lex->current_select->ref_pointer_array_size); all_fields.push_front(order_item); /* Add new field to field list. */ ref_pointer_array[el]= order_item; /* @@ -20855,6 +20859,8 @@ create_distinct_group(THD *thd, Item **ref_pointer_array, */ Item_field *new_item= new Item_field(thd, (Item_field*)item); int el= all_fields.elements; + DBUG_ASSERT(all_fields.elements <= + thd->lex->current_select->ref_pointer_array_size); orig_ref_pointer_array[el]= new_item; all_fields.push_front(new_item); ord->item= orig_ref_pointer_array + el; diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 255f876e02a..e6c5ffddfcf 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1520,6 +1520,11 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, */ lex->sql_command= old_lex->sql_command; lex->duplicates= old_lex->duplicates; + + /* Fields in this view can be used in upper select in case of merge. */ + if (table->select_lex) + table->select_lex->select_n_where_fields+= + lex->select_lex.select_n_where_fields; } /* This method has a dependency on the proper lock type being set, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index a49dea6380e..11d7efdbadf 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -9872,6 +9872,15 @@ table_factor: sel->add_joined_table($$); lex->pop_context(); lex->nest_level--; + /* + Fields in derived table can be used in upper select in + case of merge. We do not add HAVING fields because we do + not merge such derived. We do not add union because + also do not merge them + */ + if (!sel->next_select()) + $2->select_n_where_fields+= + sel->select_n_where_fields; } /*else if (($3->select_lex && $3->select_lex->master_unit()->is_union() && From 6c8f650ea0268f7b47f772efb2e3005b86a19edf Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Mon, 9 Nov 2015 16:17:17 +0100 Subject: [PATCH 53/67] MDEV-9089 Server crashes in MDL_key::mdl_key_init (main.lowercase_table4 test fails) Fix : make sure that database name is converted to lowercase in check_fk_parent_table_access(), if lowercase_table_names !=0 --- sql/sql_parse.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ee52dbe58a1..6557d2d4e90 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6081,6 +6081,7 @@ bool check_fk_parent_table_access(THD *thd, table_name.str= (char *) thd->memdup(fk_key->ref_table.str, fk_key->ref_table.length+1); table_name.length= my_casedn_str(files_charset_info, table_name.str); + db_name.length = my_casedn_str(files_charset_info, db_name.str); } parent_table.init_one_table(db_name.str, db_name.length, From 83ed38d92ad27d31f0837f0c8277ed7bb21b68f6 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 11 May 2015 20:18:30 +0800 Subject: [PATCH 54/67] fix mdev-8140 --- storage/spider/spd_db_oracle.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/spider/spd_db_oracle.cc b/storage/spider/spd_db_oracle.cc index d86da799bee..422197c51fd 100644 --- a/storage/spider/spd_db_oracle.cc +++ b/storage/spider/spd_db_oracle.cc @@ -5106,7 +5106,7 @@ void spider_oracle_handler::create_tmp_bka_table_name( uint adjust_length, length; DBUG_ENTER("spider_oracle_handler::create_tmp_bka_table_name"); if (spider_param_bka_table_name_type(current_thd, - mysql_share->spider_share-> + oracle_share->spider_share-> bka_table_name_types[spider->conn_link_idx[link_idx]]) == 1) { adjust_length = From e8c1b35f180efef8bc486aadda73fef7f8febf56 Mon Sep 17 00:00:00 2001 From: Monty Date: Thu, 12 Nov 2015 14:51:01 +0200 Subject: [PATCH 55/67] MDEV-8476 Race condition in slave SQL thread shutdown Patch backported from MariaDB 10.1 - Ensure that we wait with cleanup() until slave thread has stopped. - Added signal_thd_deleted() to signal close_connections() that all THD's has been freed. Other things - Removed not needed calls to THD_CHECK_SENTRY() when we are calling 'delete thd'. --- sql/mysqld.cc | 42 +++++++++++++++++++++++++----------------- sql/mysqld.h | 3 ++- sql/slave.cc | 18 ++++++++++++++---- 3 files changed, 41 insertions(+), 22 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index bc4d857d704..2e325ab352e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -475,7 +475,7 @@ ulong delay_key_write_options; uint protocol_version; uint lower_case_table_names; ulong tc_heuristic_recover= 0; -int32 thread_count; +int32 thread_count, service_thread_count; int32 thread_running; int32 slave_open_temp_tables; ulong thread_created; @@ -1708,7 +1708,7 @@ static void close_connections(void) /* All threads has now been aborted */ DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count)); mysql_mutex_lock(&LOCK_thread_count); - while (thread_count) + while (thread_count || service_thread_count) { mysql_cond_wait(&COND_thread_count, &LOCK_thread_count); DBUG_PRINT("quit",("One thread died (count=%u)",thread_count)); @@ -2730,8 +2730,27 @@ void delete_running_thd(THD *thd) delete thd; dec_thread_running(); thread_safe_decrement32(&thread_count, &thread_count_lock); - if (!thread_count) + signal_thd_deleted(); +} + + +/* + Send a signal to unblock close_conneciton() if there is no more + threads running with a THD attached + + It's safe to check for thread_count and service_thread_count outside + of a mutex as we are only interested to see if they where decremented + to 0 by a previous unlink_thd() call. + + We should only signal COND_thread_count if both variables are 0, + false positives are ok. +*/ + +void signal_thd_deleted() +{ + if (!thread_count && ! service_thread_count) { + /* Signal close_connections() that all THD's are freed */ mysql_mutex_lock(&LOCK_thread_count); mysql_cond_broadcast(&COND_thread_count); mysql_mutex_unlock(&LOCK_thread_count); @@ -2887,19 +2906,7 @@ bool one_thread_per_connection_end(THD *thd, bool put_in_cache) if (put_in_cache && cache_thread()) DBUG_RETURN(0); // Thread is reused - /* - It's safe to check for thread_count outside of the mutex - as we are only interested to see if it was counted to 0 by the - above unlink_thd() call. We should only signal COND_thread_count if - thread_count is likely to be 0. (false positives are ok) - */ - if (!thread_count) - { - mysql_mutex_lock(&LOCK_thread_count); - DBUG_PRINT("signal", ("Broadcasting COND_thread_count")); - mysql_cond_broadcast(&COND_thread_count); - mysql_mutex_unlock(&LOCK_thread_count); - } + signal_thd_deleted(); DBUG_LEAVE; // Must match DBUG_ENTER() #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) ERR_remove_state(0); @@ -8185,7 +8192,8 @@ static int mysql_init_variables(void) cleanup_done= 0; server_id_supplied= 0; test_flags= select_errors= dropping_tables= ha_open_options=0; - thread_count= thread_running= kill_cached_threads= wake_thread=0; + thread_count= thread_running= kill_cached_threads= wake_thread= 0; + service_thread_count= 0; slave_open_temp_tables= 0; cached_thread_count= 0; opt_endinfo= using_udf_functions= 0; diff --git a/sql/mysqld.h b/sql/mysqld.h index 156e7f99bb5..72bcc3dc686 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -59,6 +59,7 @@ void close_connection(THD *thd, uint sql_errno= 0); void handle_connection_in_main_thread(THD *thd); void create_thread_to_handle_connection(THD *thd); void delete_running_thd(THD *thd); +void signal_thd_deleted(); void unlink_thd(THD *thd); bool one_thread_per_connection_end(THD *thd, bool put_in_cache); void flush_thread_cache(); @@ -538,7 +539,7 @@ extern mysql_cond_t COND_thread_count; extern mysql_cond_t COND_manager; extern mysql_cond_t COND_slave_init; extern int32 thread_running; -extern int32 thread_count; +extern int32 thread_count, service_thread_count; extern my_atomic_rwlock_t thread_running_lock, thread_count_lock; extern my_atomic_rwlock_t slave_executed_entries_lock; diff --git a/sql/slave.cc b/sql/slave.cc index 5af48b6a793..fda7e500237 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -294,6 +294,7 @@ handle_slave_init(void *arg __attribute__((unused))) thd->thread_id= thread_id++; mysql_mutex_unlock(&LOCK_thread_count); thd->system_thread = SYSTEM_THREAD_SLAVE_INIT; + thread_safe_increment32(&service_thread_count, &thread_count_lock); thd->store_globals(); thd->security_ctx->skip_grants(); thd->set_command(COM_DAEMON); @@ -309,6 +310,8 @@ handle_slave_init(void *arg __attribute__((unused))) mysql_mutex_lock(&LOCK_thread_count); delete thd; mysql_mutex_unlock(&LOCK_thread_count); + thread_safe_decrement32(&service_thread_count, &thread_count_lock); + signal_thd_deleted(); my_thread_end(); mysql_mutex_lock(&LOCK_slave_init); @@ -2953,6 +2956,11 @@ static int init_slave_thread(THD* thd, Master_info *mi, simulate_error|= (1 << SLAVE_THD_IO);); DBUG_EXECUTE_IF("simulate_sql_slave_error_on_init", simulate_error|= (1 << SLAVE_THD_SQL);); + + thd->system_thread = (thd_type == SLAVE_THD_SQL) ? + SYSTEM_THREAD_SLAVE_SQL : SYSTEM_THREAD_SLAVE_IO; + thread_safe_increment32(&service_thread_count, &thread_count_lock); + /* We must call store_globals() before doing my_net_init() */ if (init_thr_lock() || thd->store_globals() || my_net_init(&thd->net, 0, MYF(MY_THREAD_SPECIFIC)) || @@ -2962,8 +2970,6 @@ static int init_slave_thread(THD* thd, Master_info *mi, DBUG_RETURN(-1); } - thd->system_thread = (thd_type == SLAVE_THD_SQL) ? - SYSTEM_THREAD_SLAVE_SQL : SYSTEM_THREAD_SLAVE_IO; thd->security_ctx->skip_grants(); thd->slave_thread= 1; thd->connection_name= mi->connection_name; @@ -4228,11 +4234,14 @@ err_during_init: mi->rli.relay_log.description_event_for_queue= 0; // TODO: make rpl_status part of Master_info change_rpl_status(RPL_ACTIVE_SLAVE,RPL_IDLE_SLAVE); + mysql_mutex_lock(&LOCK_thread_count); thd->unlink(); mysql_mutex_unlock(&LOCK_thread_count); - THD_CHECK_SENTRY(thd); delete thd; + thread_safe_decrement32(&service_thread_count, &thread_count_lock); + signal_thd_deleted(); + mi->abort_slave= 0; mi->slave_running= MYSQL_SLAVE_NOT_RUN; mi->io_thd= 0; @@ -4848,9 +4857,10 @@ err_during_init: mysql_mutex_unlock(&LOCK_active_mi); mysql_mutex_lock(&LOCK_thread_count); - THD_CHECK_SENTRY(thd); delete thd; mysql_mutex_unlock(&LOCK_thread_count); + thread_safe_decrement32(&service_thread_count, &thread_count_lock); + signal_thd_deleted(); DBUG_LEAVE; // Must match DBUG_ENTER() my_thread_end(); From 73d4c4dfe7a1476173dfb51fbd560b937adba82c Mon Sep 17 00:00:00 2001 From: Monty Date: Thu, 12 Nov 2015 15:16:53 +0200 Subject: [PATCH 56/67] Remove compiler warning --- storage/innobase/page/page0zip.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc index 68a8bb1532f..9f0af1af637 100644 --- a/storage/innobase/page/page0zip.cc +++ b/storage/innobase/page/page0zip.cc @@ -4928,9 +4928,12 @@ page_zip_verify_checksum( stored = static_cast(mach_read_from_4( static_cast(data) + FIL_PAGE_SPACE_OR_CHKSUM)); - ulint page_no = mach_read_from_4(static_cast (data) + FIL_PAGE_OFFSET); - ulint space_id = mach_read_from_4(static_cast - (data) + FIL_PAGE_SPACE_ID); + ulint page_no __attribute__((unused)) = + mach_read_from_4(static_cast + (data) + FIL_PAGE_OFFSET); + ulint space_id __attribute__((unused)) = + mach_read_from_4(static_cast + (data) + FIL_PAGE_SPACE_ID); #if FIL_PAGE_LSN % 8 #error "FIL_PAGE_LSN must be 64 bit aligned" From 2776159e424dc04ef162b9cc0a2bd075419e0eb4 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Thu, 12 Nov 2015 22:21:47 +0300 Subject: [PATCH 57/67] MDEV#7383: Update test results --- mysql-test/r/system_mysql_db.result | 4 ++-- mysql-test/suite/funcs_1/r/is_columns_mysql.result | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result index 4c106ae2e5a..53797e2a0a4 100644 --- a/mysql-test/r/system_mysql_db.result +++ b/mysql-test/r/system_mysql_db.result @@ -287,8 +287,8 @@ column_stats CREATE TABLE `column_stats` ( `db_name` varchar(64) COLLATE utf8_bin NOT NULL, `table_name` varchar(64) COLLATE utf8_bin NOT NULL, `column_name` varchar(64) COLLATE utf8_bin NOT NULL, - `min_value` varchar(255) COLLATE utf8_bin DEFAULT NULL, - `max_value` varchar(255) COLLATE utf8_bin DEFAULT NULL, + `min_value` varbinary(255) DEFAULT NULL, + `max_value` varbinary(255) DEFAULT NULL, `nulls_ratio` decimal(12,4) DEFAULT NULL, `avg_length` decimal(12,4) DEFAULT NULL, `avg_frequency` decimal(12,4) DEFAULT NULL, diff --git a/mysql-test/suite/funcs_1/r/is_columns_mysql.result b/mysql-test/suite/funcs_1/r/is_columns_mysql.result index e55ffe55f01..a0617727a16 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result @@ -16,8 +16,8 @@ def mysql column_stats db_name 1 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8 def mysql column_stats histogram 11 NULL YES varbinary 255 255 NULL NULL NULL NULL NULL varbinary(255) select,insert,update,references def mysql column_stats hist_size 9 NULL YES tinyint NULL NULL 3 0 NULL NULL NULL tinyint(3) unsigned select,insert,update,references def mysql column_stats hist_type 10 NULL YES enum 14 42 NULL NULL NULL utf8 utf8_bin enum('SINGLE_PREC_HB','DOUBLE_PREC_HB') select,insert,update,references -def mysql column_stats max_value 5 NULL YES varchar 255 765 NULL NULL NULL utf8 utf8_bin varchar(255) select,insert,update,references -def mysql column_stats min_value 4 NULL YES varchar 255 765 NULL NULL NULL utf8 utf8_bin varchar(255) select,insert,update,references +def mysql column_stats max_value 5 NULL YES varbinary 255 255 NULL NULL NULL NULL NULL varbinary(255) select,insert,update,references +def mysql column_stats min_value 4 NULL YES varbinary 255 255 NULL NULL NULL NULL NULL varbinary(255) select,insert,update,references def mysql column_stats nulls_ratio 6 NULL YES decimal NULL NULL 12 4 NULL NULL NULL decimal(12,4) select,insert,update,references def mysql column_stats table_name 2 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) PRI select,insert,update,references def mysql db Alter_priv 13 N NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references @@ -330,8 +330,8 @@ NULL mysql columns_priv Timestamp timestamp NULL NULL NULL NULL timestamp 3.0000 mysql column_stats db_name varchar 64 192 utf8 utf8_bin varchar(64) 3.0000 mysql column_stats table_name varchar 64 192 utf8 utf8_bin varchar(64) 3.0000 mysql column_stats column_name varchar 64 192 utf8 utf8_bin varchar(64) -3.0000 mysql column_stats min_value varchar 255 765 utf8 utf8_bin varchar(255) -3.0000 mysql column_stats max_value varchar 255 765 utf8 utf8_bin varchar(255) +1.0000 mysql column_stats min_value varbinary 255 255 NULL NULL varbinary(255) +1.0000 mysql column_stats max_value varbinary 255 255 NULL NULL varbinary(255) NULL mysql column_stats nulls_ratio decimal NULL NULL NULL NULL decimal(12,4) NULL mysql column_stats avg_length decimal NULL NULL NULL NULL decimal(12,4) NULL mysql column_stats avg_frequency decimal NULL NULL NULL NULL decimal(12,4) From a9cda4419becd34e956b1657d2cc5a07644c96bf Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 13 Nov 2015 23:43:11 +0200 Subject: [PATCH 58/67] MDEV-8066 Crash on unloading semisync_master plugin Bug was that ReplSemiSyncMaster::commitTrx() was waiting on a condition for state to change, but didn't take into account that one could have disabled semi-sync during the wait. --- plugin/semisync/semisync_master.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugin/semisync/semisync_master.cc b/plugin/semisync/semisync_master.cc index bb9eb96f6d7..af5eb9d090d 100644 --- a/plugin/semisync/semisync_master.cc +++ b/plugin/semisync/semisync_master.cc @@ -477,6 +477,7 @@ void ReplSemiSyncMaster::add_slave() void ReplSemiSyncMaster::remove_slave() { lock(); + assert(rpl_semi_sync_master_clients > 0); rpl_semi_sync_master_clients--; /* Only switch off if semi-sync is enabled and is on */ @@ -744,8 +745,10 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name, /* At this point, the binlog file and position of this transaction must have been removed from ActiveTranx. + active_tranxs_ may be NULL if someone disabled semi sync during + cond_timewait() */ - assert(thd_killed(NULL) || + assert(thd_killed(NULL) || !active_tranxs_ || !active_tranxs_->is_tranx_end_pos(trx_wait_binlog_name, trx_wait_binlog_pos)); From 063a51ca5d4e390cebf225e653c67c733c1a695e Mon Sep 17 00:00:00 2001 From: Monty Date: Sat, 14 Nov 2015 07:21:03 +0200 Subject: [PATCH 59/67] Fixed buildbot failures with system_mysql_db_fix --- mysql-test/r/system_mysql_db_fix40123.result | 4 ++-- mysql-test/r/system_mysql_db_fix50030.result | 4 ++-- mysql-test/r/system_mysql_db_fix50117.result | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/system_mysql_db_fix40123.result b/mysql-test/r/system_mysql_db_fix40123.result index 4c106ae2e5a..53797e2a0a4 100644 --- a/mysql-test/r/system_mysql_db_fix40123.result +++ b/mysql-test/r/system_mysql_db_fix40123.result @@ -287,8 +287,8 @@ column_stats CREATE TABLE `column_stats` ( `db_name` varchar(64) COLLATE utf8_bin NOT NULL, `table_name` varchar(64) COLLATE utf8_bin NOT NULL, `column_name` varchar(64) COLLATE utf8_bin NOT NULL, - `min_value` varchar(255) COLLATE utf8_bin DEFAULT NULL, - `max_value` varchar(255) COLLATE utf8_bin DEFAULT NULL, + `min_value` varbinary(255) DEFAULT NULL, + `max_value` varbinary(255) DEFAULT NULL, `nulls_ratio` decimal(12,4) DEFAULT NULL, `avg_length` decimal(12,4) DEFAULT NULL, `avg_frequency` decimal(12,4) DEFAULT NULL, diff --git a/mysql-test/r/system_mysql_db_fix50030.result b/mysql-test/r/system_mysql_db_fix50030.result index 4c106ae2e5a..53797e2a0a4 100644 --- a/mysql-test/r/system_mysql_db_fix50030.result +++ b/mysql-test/r/system_mysql_db_fix50030.result @@ -287,8 +287,8 @@ column_stats CREATE TABLE `column_stats` ( `db_name` varchar(64) COLLATE utf8_bin NOT NULL, `table_name` varchar(64) COLLATE utf8_bin NOT NULL, `column_name` varchar(64) COLLATE utf8_bin NOT NULL, - `min_value` varchar(255) COLLATE utf8_bin DEFAULT NULL, - `max_value` varchar(255) COLLATE utf8_bin DEFAULT NULL, + `min_value` varbinary(255) DEFAULT NULL, + `max_value` varbinary(255) DEFAULT NULL, `nulls_ratio` decimal(12,4) DEFAULT NULL, `avg_length` decimal(12,4) DEFAULT NULL, `avg_frequency` decimal(12,4) DEFAULT NULL, diff --git a/mysql-test/r/system_mysql_db_fix50117.result b/mysql-test/r/system_mysql_db_fix50117.result index 4c106ae2e5a..53797e2a0a4 100644 --- a/mysql-test/r/system_mysql_db_fix50117.result +++ b/mysql-test/r/system_mysql_db_fix50117.result @@ -287,8 +287,8 @@ column_stats CREATE TABLE `column_stats` ( `db_name` varchar(64) COLLATE utf8_bin NOT NULL, `table_name` varchar(64) COLLATE utf8_bin NOT NULL, `column_name` varchar(64) COLLATE utf8_bin NOT NULL, - `min_value` varchar(255) COLLATE utf8_bin DEFAULT NULL, - `max_value` varchar(255) COLLATE utf8_bin DEFAULT NULL, + `min_value` varbinary(255) DEFAULT NULL, + `max_value` varbinary(255) DEFAULT NULL, `nulls_ratio` decimal(12,4) DEFAULT NULL, `avg_length` decimal(12,4) DEFAULT NULL, `avg_frequency` decimal(12,4) DEFAULT NULL, From e669a5fd87b28158cbb4454b4bcce7fe4a4ef8b8 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 17 Nov 2015 18:33:08 +0100 Subject: [PATCH 60/67] MDEV-7588 Add thd_wait_begin/end to notify threadpool of binlog waits --- sql/log.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/log.cc b/sql/log.cc index 0940cb9b56c..a87ec7225d1 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -6296,11 +6296,13 @@ int MYSQL_BIN_LOG::wait_for_update_bin_log(THD* thd, int ret= 0; DBUG_ENTER("wait_for_update_bin_log"); + thd_wait_begin(thd, THD_WAIT_BINLOG); if (!timeout) mysql_cond_wait(&update_cond, &LOCK_log); else ret= mysql_cond_timedwait(&update_cond, &LOCK_log, const_cast(timeout)); + thd_wait_end(thd); DBUG_RETURN(ret); } From dd90dae3c0f639ebc29be3477c8732ecefa6de1d Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 17 Nov 2015 18:33:08 +0100 Subject: [PATCH 61/67] MDEV-7588 Add thd_wait_begin/end to notify threadpool of binlog waits --- sql/log.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/log.cc b/sql/log.cc index cf7f64f57d2..d9899267068 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -7739,11 +7739,13 @@ int MYSQL_BIN_LOG::wait_for_update_bin_log(THD* thd, int ret= 0; DBUG_ENTER("wait_for_update_bin_log"); + thd_wait_begin(thd, THD_WAIT_BINLOG); if (!timeout) mysql_cond_wait(&update_cond, &LOCK_log); else ret= mysql_cond_timedwait(&update_cond, &LOCK_log, const_cast(timeout)); + thd_wait_end(thd); DBUG_RETURN(ret); } From 726162989bdffca6af4a83c018a7d8eafeb82e6f Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 18 Nov 2015 10:58:51 +0100 Subject: [PATCH 62/67] feedback plugin debug make it possible to change feedback plugin wait intervals * only in debug builds * and force the feedback report to be ignored update the test to use this feature --- mysql-test/include/default_mysqld.cnf | 3 ++ .../plugins/r/feedback_plugin_install.result | 3 +- .../plugins/r/feedback_plugin_load.result | 3 +- .../plugins/r/feedback_plugin_send.result | 9 +++-- .../plugins/t/feedback_plugin_install.test | 4 ++- .../suite/plugins/t/feedback_plugin_load.test | 3 +- .../suite/plugins/t/feedback_plugin_send.test | 15 +++------ plugin/feedback/feedback.cc | 33 +++++++++++++++++++ plugin/feedback/feedback.h | 4 +++ plugin/feedback/sender_thread.cc | 6 ++-- 10 files changed, 61 insertions(+), 22 deletions(-) diff --git a/mysql-test/include/default_mysqld.cnf b/mysql-test/include/default_mysqld.cnf index 96848c39f11..40d699ce759 100644 --- a/mysql-test/include/default_mysqld.cnf +++ b/mysql-test/include/default_mysqld.cnf @@ -38,6 +38,9 @@ max_heap_table_size= 1M loose-aria-pagecache-buffer-size=8M loose-feedback-user-info= mysql-test +loose-feedback-debug-startup-interval=20 +loose-feedback-debug-first-interval=60 +loose-feedback-debug-interval=60 loose-innodb_data_file_path= ibdata1:10M:autoextend loose-innodb_buffer_pool_size= 8M diff --git a/mysql-test/suite/plugins/r/feedback_plugin_install.result b/mysql-test/suite/plugins/r/feedback_plugin_install.result index 37d26b48501..c52fdb8f85b 100644 --- a/mysql-test/suite/plugins/r/feedback_plugin_install.result +++ b/mysql-test/suite/plugins/r/feedback_plugin_install.result @@ -3,7 +3,8 @@ select plugin_status from information_schema.plugins where plugin_name='feedback plugin_status ACTIVE select * from information_schema.feedback where variable_name like 'feed%' - and variable_name not like '%_uid'; + and variable_name not like '%_uid' + and variable_name not like '%debug%'; VARIABLE_NAME VARIABLE_VALUE FEEDBACK used 1 FEEDBACK version 1.1 diff --git a/mysql-test/suite/plugins/r/feedback_plugin_load.result b/mysql-test/suite/plugins/r/feedback_plugin_load.result index ea6eae98601..e2cf3247022 100644 --- a/mysql-test/suite/plugins/r/feedback_plugin_load.result +++ b/mysql-test/suite/plugins/r/feedback_plugin_load.result @@ -6,7 +6,8 @@ SELECT variable_value = @feedback_used + 1 FROM information_schema.feedback wher variable_value = @feedback_used + 1 1 select * from information_schema.feedback where variable_name like 'feed%' - and variable_name not like '%_uid' and variable_name not like 'FEEDBACK used'; + and variable_name not like '%_uid' and variable_name not like 'FEEDBACK used' + and variable_name not like '%debug%'; VARIABLE_NAME VARIABLE_VALUE FEEDBACK version 1.1 FEEDBACK_SEND_RETRY_WAIT 60 diff --git a/mysql-test/suite/plugins/r/feedback_plugin_send.result b/mysql-test/suite/plugins/r/feedback_plugin_send.result index 90a37f7ffbc..56a4e37981c 100644 --- a/mysql-test/suite/plugins/r/feedback_plugin_send.result +++ b/mysql-test/suite/plugins/r/feedback_plugin_send.result @@ -6,14 +6,13 @@ SELECT variable_value = @feedback_used + 1 FROM information_schema.feedback wher variable_value = @feedback_used + 1 1 select * from information_schema.feedback where variable_name like 'feed%' - and variable_name not like '%_uid' and variable_name not like 'FEEDBACK used'; + and variable_name not like '%_uid' and variable_name not like 'FEEDBACK used' + and variable_name not like '%debug%'; VARIABLE_NAME VARIABLE_VALUE FEEDBACK version 1.1 FEEDBACK_SEND_RETRY_WAIT 60 FEEDBACK_SEND_TIMEOUT 60 FEEDBACK_URL http://mariadb.org/feedback_plugin/post FEEDBACK_USER_INFO mysql-test -feedback plugin: report to 'http://mariadb.org/feedback_plugin/post' was sent -feedback plugin: server replied 'ok' -feedback plugin: report to 'http://mariadb.org/feedback_plugin/post' was sent -feedback plugin: server replied 'ok' +6: feedback plugin: report to 'http://mariadb.org/feedback_plugin/post' was sent +6: feedback plugin: server replied 'ok' diff --git a/mysql-test/suite/plugins/t/feedback_plugin_install.test b/mysql-test/suite/plugins/t/feedback_plugin_install.test index 81343c436c3..559dcebfc05 100644 --- a/mysql-test/suite/plugins/t/feedback_plugin_install.test +++ b/mysql-test/suite/plugins/t/feedback_plugin_install.test @@ -10,6 +10,8 @@ select plugin_status from information_schema.plugins where plugin_name='feedback --replace_result https http --sorted_result select * from information_schema.feedback where variable_name like 'feed%' - and variable_name not like '%_uid'; + and variable_name not like '%_uid' + and variable_name not like '%debug%'; + uninstall plugin feedback; diff --git a/mysql-test/suite/plugins/t/feedback_plugin_load.test b/mysql-test/suite/plugins/t/feedback_plugin_load.test index f7c62b96b49..f626f1b0125 100644 --- a/mysql-test/suite/plugins/t/feedback_plugin_load.test +++ b/mysql-test/suite/plugins/t/feedback_plugin_load.test @@ -24,4 +24,5 @@ SELECT variable_value = @feedback_used + 1 FROM information_schema.feedback wher --replace_result https http --sorted_result select * from information_schema.feedback where variable_name like 'feed%' - and variable_name not like '%_uid' and variable_name not like 'FEEDBACK used'; + and variable_name not like '%_uid' and variable_name not like 'FEEDBACK used' + and variable_name not like '%debug%'; diff --git a/mysql-test/suite/plugins/t/feedback_plugin_send.test b/mysql-test/suite/plugins/t/feedback_plugin_send.test index 31542c33482..31ab213831e 100644 --- a/mysql-test/suite/plugins/t/feedback_plugin_send.test +++ b/mysql-test/suite/plugins/t/feedback_plugin_send.test @@ -25,20 +25,15 @@ sleep 310; --let $shutdown_timeout= 60 source include/restart_mysqld.inc; -replace_result https http; +replace_result https http 2 6; perl; $log_error= $ENV{'MYSQLTEST_VARDIR'} . '/log/mysqld.1.err'; open(LOG, '<', $log_error) or die "open(< $log_error): $!"; - # Get the first few rows (as there may be different number rows in the log) - $i= 0; - while ($_=) - { - if (/feedback plugin:.*/) - { - print "$&\n"; - break if ($i++ >= 3); - } + %logg=(); + while ($_=) { + $logg{$&}++ if /feedback plugin:.*/; } + print "$logg{$_}: $_\n" for sort keys %logg; close LOG; EOF diff --git a/plugin/feedback/feedback.cc b/plugin/feedback/feedback.cc index 9bf2fcb99bc..f87caa54cbc 100644 --- a/plugin/feedback/feedback.cc +++ b/plugin/feedback/feedback.cc @@ -22,6 +22,10 @@ extern ST_SCHEMA_TABLE schema_tables[]; namespace feedback { +#ifndef DBUG_OFF +ulong debug_startup_interval, debug_first_interval, debug_interval; +#endif + char server_uid_buf[SERVER_UID_SIZE+1]; ///< server uid will be written here /* backing store for system variables */ @@ -249,6 +253,18 @@ static int init(void *p) prepare_linux_info(); +#ifndef DBUG_OFF + if (startup_interval != debug_startup_interval || + first_interval != debug_first_interval || + interval != debug_interval) + { + startup_interval= debug_startup_interval; + first_interval= debug_first_interval; + interval= debug_interval; + user_info= "mysql-test"; + } +#endif + url_count= 0; if (*url) { @@ -347,12 +363,29 @@ static MYSQL_SYSVAR_ULONG(send_retry_wait, send_retry_wait, PLUGIN_VAR_RQCMDARG, "Wait this many seconds before retrying a failed send.", NULL, NULL, 60, 1, 60*60*24, 1); +#ifndef DBUG_OFF +static MYSQL_SYSVAR_ULONG(debug_startup_interval, debug_startup_interval, + PLUGIN_VAR_RQCMDARG, "for debugging only", + NULL, NULL, startup_interval, 1, INT_MAX32, 1); +static MYSQL_SYSVAR_ULONG(debug_first_interval, debug_first_interval, + PLUGIN_VAR_RQCMDARG, "for debugging only", + NULL, NULL, first_interval, 1, INT_MAX32, 1); +static MYSQL_SYSVAR_ULONG(debug_interval, debug_interval, + PLUGIN_VAR_RQCMDARG, "for debugging only", + NULL, NULL, interval, 1, INT_MAX32, 1); +#endif + static struct st_mysql_sys_var* settings[] = { MYSQL_SYSVAR(server_uid), MYSQL_SYSVAR(user_info), MYSQL_SYSVAR(url), MYSQL_SYSVAR(send_timeout), MYSQL_SYSVAR(send_retry_wait), +#ifndef DBUG_OFF + MYSQL_SYSVAR(debug_startup_interval), + MYSQL_SYSVAR(debug_first_interval), + MYSQL_SYSVAR(debug_interval), +#endif NULL }; diff --git a/plugin/feedback/feedback.h b/plugin/feedback/feedback.h index c5acbb5ef72..63aa4f8db8a 100644 --- a/plugin/feedback/feedback.h +++ b/plugin/feedback/feedback.h @@ -58,6 +58,10 @@ class Url { extern Url **urls; extern uint url_count; +extern time_t startup_interval; +extern time_t first_interval; +extern time_t interval; + /* these are used to communicate with the background thread */ extern mysql_mutex_t sleep_mutex; extern mysql_cond_t sleep_condition; diff --git a/plugin/feedback/sender_thread.cc b/plugin/feedback/sender_thread.cc index 4ab45998484..abc3d0a18e6 100644 --- a/plugin/feedback/sender_thread.cc +++ b/plugin/feedback/sender_thread.cc @@ -25,9 +25,9 @@ static my_thread_id thd_thread_id; ///< its thread_id static size_t needed_size= 20480; -static const time_t startup_interval= 60*5; ///< in seconds (5 minutes) -static const time_t first_interval= 60*60*24; ///< in seconds (one day) -static const time_t interval= 60*60*24*7; ///< in seconds (one week) +time_t startup_interval= 60*5; ///< in seconds (5 minutes) +time_t first_interval= 60*60*24; ///< in seconds (one day) +time_t interval= 60*60*24*7; ///< in seconds (one week) /** reads the rows from a table and puts them, concatenated, in a String From 43a5090980ac0ab9695587979b9068b6bf849d64 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 18 Nov 2015 11:20:59 +0100 Subject: [PATCH 63/67] MDEV-9051 mysqld got signal 11, after upgrade to 10.1.8 feedback plugin needs to set tables->select_lex properly --- mysql-test/suite/plugins/r/feedback_plugin_send.result | 1 + mysql-test/suite/plugins/t/feedback_plugin_send.test | 6 +++++- plugin/feedback/sender_thread.cc | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/plugins/r/feedback_plugin_send.result b/mysql-test/suite/plugins/r/feedback_plugin_send.result index 56a4e37981c..10378673829 100644 --- a/mysql-test/suite/plugins/r/feedback_plugin_send.result +++ b/mysql-test/suite/plugins/r/feedback_plugin_send.result @@ -14,5 +14,6 @@ FEEDBACK_SEND_RETRY_WAIT 60 FEEDBACK_SEND_TIMEOUT 60 FEEDBACK_URL http://mariadb.org/feedback_plugin/post FEEDBACK_USER_INFO mysql-test +set global sql_mode=ONLY_FULL_GROUP_BY; 6: feedback plugin: report to 'http://mariadb.org/feedback_plugin/post' was sent 6: feedback plugin: server replied 'ok' diff --git a/mysql-test/suite/plugins/t/feedback_plugin_send.test b/mysql-test/suite/plugins/t/feedback_plugin_send.test index 31ab213831e..b28f9d4cb38 100644 --- a/mysql-test/suite/plugins/t/feedback_plugin_send.test +++ b/mysql-test/suite/plugins/t/feedback_plugin_send.test @@ -13,7 +13,11 @@ if (!$MTR_FEEDBACK_PLUGIN) { # Let's wait, and hope that mtr is started with --parallel and # is doing some work in other workers. # -sleep 310; + +sleep 100; +set global sql_mode=ONLY_FULL_GROUP_BY; +sleep 210; + # The test expects that the plugin will send a report at least 2 times, # now (5 min after loading) and on server shutdown which happens below. diff --git a/plugin/feedback/sender_thread.cc b/plugin/feedback/sender_thread.cc index abc3d0a18e6..f32bf36a634 100644 --- a/plugin/feedback/sender_thread.cc +++ b/plugin/feedback/sender_thread.cc @@ -124,6 +124,7 @@ static int prepare_for_fill(TABLE_LIST *tables) if (!tables->table) return 1; + tables->select_lex= thd->lex->current_select; tables->table->pos_in_table_list= tables; return 0; From f383cbcb03c499a935f4c59dd5101b2a6470c5c6 Mon Sep 17 00:00:00 2001 From: Monty Date: Wed, 18 Nov 2015 14:46:30 +0200 Subject: [PATCH 64/67] Added some selects to rpl_parallel2.test to find out where it fails in buildbot --- mysql-test/suite/rpl/r/rpl_parallel2.result | 6 ++++++ mysql-test/suite/rpl/t/rpl_parallel2.test | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/mysql-test/suite/rpl/r/rpl_parallel2.result b/mysql-test/suite/rpl/r/rpl_parallel2.result index 2ca73738d84..f79661ee6fb 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel2.result +++ b/mysql-test/suite/rpl/r/rpl_parallel2.result @@ -88,6 +88,12 @@ a b 18 0 19 0 UNLOCK TABLES; +SELECT "after UNLOCK TABLES" as state; +state +after UNLOCK TABLES +SELECT "after reap of STOP SLAVE" as state; +state +after reap of STOP SLAVE include/wait_for_slave_to_stop.inc include/start_slave.inc SELECT * FROM t2 ORDER BY a; diff --git a/mysql-test/suite/rpl/t/rpl_parallel2.test b/mysql-test/suite/rpl/t/rpl_parallel2.test index 50617c63024..3a9c801175f 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel2.test +++ b/mysql-test/suite/rpl/t/rpl_parallel2.test @@ -162,9 +162,13 @@ SELECT * FROM t2 ORDER BY a; --connection s2 UNLOCK TABLES; +SELECT "after UNLOCK TABLES" as state; + --connection s1 reap; +SELECT "after reap of STOP SLAVE" as state; + --connection server_2 --source include/wait_for_slave_to_stop.inc --source include/start_slave.inc From c2ec897745f37c1479dc9be3a2a3b476e4ed694f Mon Sep 17 00:00:00 2001 From: Monty Date: Wed, 18 Nov 2015 17:42:39 +0200 Subject: [PATCH 65/67] Fixed buildbot failures on Solaris 64 bit rpl/rpl_mdev382 ; Wrong replace in show_binlog_events2.inc binlog/database ; Different error on Solaris if file exists mroonga/repair_table_no_index_file ; Different system error on Solaris partition_not_blackhole ; Different error on Solaris partition_myisam ; Different error on Solaris Some other failures in mroonga was because have_32bit.inc didn't correctly detect 64 bits on Solaris. Fixed using DEFAULT_MACHINE instead of MACHINE_TYPE for Sys_version_compile_machine. --- config.h.cmake | 1 + mysql-test/extra/binlog_tests/database.test | 2 +- mysql-test/include/show_binlog_events2.inc | 3 ++- mysql-test/t/partition_myisam.test | 1 + mysql-test/t/partition_not_blackhole.test | 3 +++ sql/sys_vars.cc | 2 +- .../mroonga/wrapper/t/repair_table_no_index_file.test | 3 +++ 7 files changed, 12 insertions(+), 3 deletions(-) diff --git a/config.h.cmake b/config.h.cmake index b037464df88..33ec17e49c7 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -491,6 +491,7 @@ #define SYSTEM_TYPE "@SYSTEM_TYPE@" #define MACHINE_TYPE "@CMAKE_SYSTEM_PROCESSOR@" +#define DEFAULT_MACHINE "@DEFAULT_MACHINE@" #cmakedefine HAVE_DTRACE 1 #cmakedefine SIGNAL_WITH_VIO_CLOSE 1 diff --git a/mysql-test/extra/binlog_tests/database.test b/mysql-test/extra/binlog_tests/database.test index cd0266434ff..82e8b396357 100644 --- a/mysql-test/extra/binlog_tests/database.test +++ b/mysql-test/extra/binlog_tests/database.test @@ -52,7 +52,7 @@ eval SELECT 'hello' INTO OUTFILE 'fake_file.$prefix'; # Use '/' instead of '\' in the error message. On windows platform, dir is # formed with '\'. ---replace_regex /\\testing_1\\*/\/testing_1\// /66/39/ +--replace_regex /\\testing_1\\*/\/testing_1\// /66/39/ /17/39/ /File exists/Directory not empty/ --error 1010 DROP DATABASE testing_1; let $wait_binlog_event= DROP TABLE IF EXIST; diff --git a/mysql-test/include/show_binlog_events2.inc b/mysql-test/include/show_binlog_events2.inc index e72522dc272..b036709b81d 100644 --- a/mysql-test/include/show_binlog_events2.inc +++ b/mysql-test/include/show_binlog_events2.inc @@ -10,7 +10,8 @@ if ($binlog_file) { --let $_in_binlog_file=in '$binlog_file' } ---replace_result $_binlog_start $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--let $_from_binlog_start=from $_binlog_start +--replace_result "$_from_binlog_start" "from " $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --replace_column 2 # 5 # --replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/ /file_id=[0-9]+/file_id=#/ /GTID [0-9]+-[0-9]+-[0-9]+/GTID #-#-#/ --eval show binlog events $_in_binlog_file from $_binlog_start diff --git a/mysql-test/t/partition_myisam.test b/mysql-test/t/partition_myisam.test index bce0c6f009c..d07637057e0 100644 --- a/mysql-test/t/partition_myisam.test +++ b/mysql-test/t/partition_myisam.test @@ -123,6 +123,7 @@ CHECK TABLE t1; SELECT * FROM t1; --echo # Note that it is currently impossible to drop a partitioned table --echo # without the .par file +--replace_result "Not owner" "Operation not permitted" --error ER_GET_ERRNO DROP TABLE t1; --remove_file $MYSQLD_DATADIR/test/t1.frm diff --git a/mysql-test/t/partition_not_blackhole.test b/mysql-test/t/partition_not_blackhole.test index 3731d659ad0..fe7452432b2 100644 --- a/mysql-test/t/partition_not_blackhole.test +++ b/mysql-test/t/partition_not_blackhole.test @@ -19,6 +19,9 @@ SHOW TABLES; --replace_result $MYSQLD_DATADIR ./ --error ER_NOT_FORM_FILE SHOW CREATE TABLE t1; + +# The replace is needed for Solaris +--replace_result "Not owner" "Operation not permitted" --error ER_GET_ERRNO DROP TABLE t1; --list_files $MYSQLD_DATADIR/test t1* diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 12aaf0a7e7d..d8970263ed7 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3291,7 +3291,7 @@ static Sys_var_charptr Sys_version_compile_machine( "version_compile_machine", "version_compile_machine", READ_ONLY SHOW_VALUE_IN_HELP GLOBAL_VAR(server_version_compile_machine_ptr), NO_CMD_LINE, - IN_SYSTEM_CHARSET, DEFAULT(MACHINE_TYPE)); + IN_SYSTEM_CHARSET, DEFAULT(DEFAULT_MACHINE)); static char *server_version_compile_os_ptr; static Sys_var_charptr Sys_version_compile_os( diff --git a/storage/mroonga/mysql-test/mroonga/wrapper/t/repair_table_no_index_file.test b/storage/mroonga/mysql-test/mroonga/wrapper/t/repair_table_no_index_file.test index 147d9672eae..b5a7f2c860a 100644 --- a/storage/mroonga/mysql-test/mroonga/wrapper/t/repair_table_no_index_file.test +++ b/storage/mroonga/mysql-test/mroonga/wrapper/t/repair_table_no_index_file.test @@ -41,6 +41,9 @@ SELECT * FROM diaries WHERE MATCH(body) AGAINST("starting"); FLUSH TABLES; # Error ER_CANT_OPEN_FILE syscall error 'repair_test.mrn.0000104' (No such file or directory) +# The (Error 0)[0]" replaces is for Solaris +# +--replace_result "(Error 0)[0]" "(No such file or directory)" --error ER_CANT_OPEN_FILE SELECT * FROM diaries WHERE MATCH(body) AGAINST("starting"); From f91798dd1c9e178061ba58c88a42b9cb3701385d Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Wed, 18 Nov 2015 21:31:45 +0300 Subject: [PATCH 66/67] MDEV-7370: Server deadlocks on renaming a table for which persistent statistics exists RENAME TABLE code tries to update EITS statistics. It hung, because it used an index on (db_name,table_name) to find the table, and attempted to update these values at the same time. The fix is do what SQL UPDATE statement does when updating index that it's used for scanning: - First, buffer the rowids of rows to be updated, - then make the second pass to actually update the rows Also fixed the call to rename_table_in_stat_tables() in sql_rename.cc to pass the correct new database (before, it passed old db_name so cross- database renames were not handled correctly). Variant #2, with review feedback addressed. --- mysql-test/r/stat_tables.result | 95 +++++++++++++++++++ mysql-test/r/stat_tables_innodb.result | 95 +++++++++++++++++++ mysql-test/t/stat_tables.test | 73 ++++++++++++++ sql/sql_rename.cc | 3 +- sql/sql_statistics.cc | 126 ++++++++++++++++++++++++- 5 files changed, 389 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/stat_tables.result b/mysql-test/r/stat_tables.result index 285284596c4..fcced761283 100644 --- a/mysql-test/r/stat_tables.result +++ b/mysql-test/r/stat_tables.result @@ -421,4 +421,99 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index 1 SIMPLE t2 ALL NULL NULL NULL NULL 2 Using where DROP TABLE t1,t2; +# +# MDEV-7370: Server deadlocks on renaming a table for which persistent statistics exists +# +drop database if exists db1; +drop database if exists db1; +create database db1; +create database db2; +use db1; +# +# First, run the original testcase: +# +create table t1 (i int); +insert into t1 values (10),(20); +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +db1.t1 analyze status Engine-independent statistics collected +db1.t1 analyze status OK +rename table t1 to db2.t1; +# Verify that stats in the old database are gone: +select * from mysql.column_stats where db_name='db1' and table_name='t1'; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +select * from mysql.table_stats where db_name='db1' and table_name='t1'; +db_name table_name cardinality +# Verify that stats are present in the new database: +select * from mysql.column_stats where db_name='db2' and table_name='t1'; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +db2 t1 i 10 20 0.0000 4.0000 1.0000 0 NULL NULL +select * from mysql.table_stats where db_name='db2' and table_name='t1'; +db_name table_name cardinality +db2 t1 2 +# +# Now, try with more than one column and with indexes: +# +use test; +create table t1(a int primary key); +insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +use db1; +create table t2 (a int, b int, c int, key IDX1(a), key IDX2(a,b)); +insert into t2 select a/10, a/2, a from test.t1; +analyze table t2 persistent for all; +Table Op Msg_type Msg_text +db1.t2 analyze status Engine-independent statistics collected +db1.t2 analyze status Table is already up to date +alter table t2 rename db2.t2; +# Verify that stats in the old database are gone: +select * from mysql.table_stats where db_name='db1' and table_name='t2'; +db_name table_name cardinality +select * from mysql.column_stats where db_name='db1' and table_name='t2'; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +select * from mysql.index_stats where db_name='db1' and table_name='t2'; +db_name table_name index_name prefix_arity avg_frequency +# Verify that stats are present in the new database: +select * from mysql.table_stats where db_name='db2' and table_name='t2'; +db_name table_name cardinality +db2 t2 10 +select * from mysql.column_stats where db_name='db2' and table_name='t2'; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +db2 t2 a 0 1 0.0000 4.0000 5.0000 0 NULL NULL +db2 t2 b 0 5 0.0000 4.0000 1.6667 0 NULL NULL +db2 t2 c 0 9 0.0000 4.0000 1.0000 0 NULL NULL +select * from mysql.index_stats where db_name='db2' and table_name='t2'; +db_name table_name index_name prefix_arity avg_frequency +db2 t2 IDX1 1 5.0000 +db2 t2 IDX2 1 5.0000 +db2 t2 IDX2 2 1.6667 +use db2; +# +# Now, rename within the same database and verify: +# +rename table t2 to t3; +# No stats under old name: +select * from mysql.table_stats where db_name='db2' and table_name='t2'; +db_name table_name cardinality +select * from mysql.column_stats where db_name='db2' and table_name='t2'; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +select * from mysql.index_stats where db_name='db2' and table_name='t2'; +db_name table_name index_name prefix_arity avg_frequency +# Stats under the new name: +select * from mysql.table_stats where db_name='db2' and table_name='t3'; +db_name table_name cardinality +db2 t3 10 +select * from mysql.column_stats where db_name='db2' and table_name='t3'; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +db2 t3 a 0 1 0.0000 4.0000 5.0000 0 NULL NULL +db2 t3 b 0 5 0.0000 4.0000 1.6667 0 NULL NULL +db2 t3 c 0 9 0.0000 4.0000 1.0000 0 NULL NULL +select * from mysql.index_stats where db_name='db2' and table_name='t3'; +db_name table_name index_name prefix_arity avg_frequency +db2 t3 IDX1 1 5.0000 +db2 t3 IDX2 1 5.0000 +db2 t3 IDX2 2 1.6667 +use test; +drop database db1; +drop database db2; +drop table t1; set use_stat_tables=@save_use_stat_tables; diff --git a/mysql-test/r/stat_tables_innodb.result b/mysql-test/r/stat_tables_innodb.result index 301c093ce9c..0e866755532 100644 --- a/mysql-test/r/stat_tables_innodb.result +++ b/mysql-test/r/stat_tables_innodb.result @@ -448,6 +448,101 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index 1 SIMPLE t2 ALL NULL NULL NULL NULL 2 Using where DROP TABLE t1,t2; +# +# MDEV-7370: Server deadlocks on renaming a table for which persistent statistics exists +# +drop database if exists db1; +drop database if exists db1; +create database db1; +create database db2; +use db1; +# +# First, run the original testcase: +# +create table t1 (i int); +insert into t1 values (10),(20); +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +db1.t1 analyze status Engine-independent statistics collected +db1.t1 analyze status OK +rename table t1 to db2.t1; +# Verify that stats in the old database are gone: +select * from mysql.column_stats where db_name='db1' and table_name='t1'; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +select * from mysql.table_stats where db_name='db1' and table_name='t1'; +db_name table_name cardinality +# Verify that stats are present in the new database: +select * from mysql.column_stats where db_name='db2' and table_name='t1'; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +db2 t1 i 10 20 0.0000 4.0000 1.0000 0 NULL NULL +select * from mysql.table_stats where db_name='db2' and table_name='t1'; +db_name table_name cardinality +db2 t1 2 +# +# Now, try with more than one column and with indexes: +# +use test; +create table t1(a int primary key); +insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +use db1; +create table t2 (a int, b int, c int, key IDX1(a), key IDX2(a,b)); +insert into t2 select a/10, a/2, a from test.t1; +analyze table t2 persistent for all; +Table Op Msg_type Msg_text +db1.t2 analyze status Engine-independent statistics collected +db1.t2 analyze status OK +alter table t2 rename db2.t2; +# Verify that stats in the old database are gone: +select * from mysql.table_stats where db_name='db1' and table_name='t2'; +db_name table_name cardinality +select * from mysql.column_stats where db_name='db1' and table_name='t2'; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +select * from mysql.index_stats where db_name='db1' and table_name='t2'; +db_name table_name index_name prefix_arity avg_frequency +# Verify that stats are present in the new database: +select * from mysql.table_stats where db_name='db2' and table_name='t2'; +db_name table_name cardinality +db2 t2 10 +select * from mysql.column_stats where db_name='db2' and table_name='t2'; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +db2 t2 a 0 1 0.0000 4.0000 5.0000 0 NULL NULL +db2 t2 b 0 5 0.0000 4.0000 1.6667 0 NULL NULL +db2 t2 c 0 9 0.0000 4.0000 1.0000 0 NULL NULL +select * from mysql.index_stats where db_name='db2' and table_name='t2'; +db_name table_name index_name prefix_arity avg_frequency +db2 t2 IDX1 1 5.0000 +db2 t2 IDX2 1 5.0000 +db2 t2 IDX2 2 1.6667 +use db2; +# +# Now, rename within the same database and verify: +# +rename table t2 to t3; +# No stats under old name: +select * from mysql.table_stats where db_name='db2' and table_name='t2'; +db_name table_name cardinality +select * from mysql.column_stats where db_name='db2' and table_name='t2'; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +select * from mysql.index_stats where db_name='db2' and table_name='t2'; +db_name table_name index_name prefix_arity avg_frequency +# Stats under the new name: +select * from mysql.table_stats where db_name='db2' and table_name='t3'; +db_name table_name cardinality +db2 t3 10 +select * from mysql.column_stats where db_name='db2' and table_name='t3'; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +db2 t3 a 0 1 0.0000 4.0000 5.0000 0 NULL NULL +db2 t3 b 0 5 0.0000 4.0000 1.6667 0 NULL NULL +db2 t3 c 0 9 0.0000 4.0000 1.0000 0 NULL NULL +select * from mysql.index_stats where db_name='db2' and table_name='t3'; +db_name table_name index_name prefix_arity avg_frequency +db2 t3 IDX1 1 5.0000 +db2 t3 IDX2 1 5.0000 +db2 t3 IDX2 2 1.6667 +use test; +drop database db1; +drop database db2; +drop table t1; set use_stat_tables=@save_use_stat_tables; set optimizer_switch=@save_optimizer_switch_for_stat_tables_test; SET SESSION STORAGE_ENGINE=DEFAULT; diff --git a/mysql-test/t/stat_tables.test b/mysql-test/t/stat_tables.test index 25ca322ca0a..4cbaa9e27c8 100644 --- a/mysql-test/t/stat_tables.test +++ b/mysql-test/t/stat_tables.test @@ -232,4 +232,77 @@ SELECT * FROM t1 STRAIGHT_JOIN t2 WHERE name IN ( 'AUS','YEM' ) AND id = 1; DROP TABLE t1,t2; +--echo # +--echo # MDEV-7370: Server deadlocks on renaming a table for which persistent statistics exists +--echo # + +--disable_warnings +drop database if exists db1; +drop database if exists db1; +--enable_warnings + +create database db1; +create database db2; +use db1; +--echo # +--echo # First, run the original testcase: +--echo # +create table t1 (i int); +insert into t1 values (10),(20); +analyze table t1 persistent for all; +rename table t1 to db2.t1; + +--echo # Verify that stats in the old database are gone: +select * from mysql.column_stats where db_name='db1' and table_name='t1'; +select * from mysql.table_stats where db_name='db1' and table_name='t1'; + +--echo # Verify that stats are present in the new database: +select * from mysql.column_stats where db_name='db2' and table_name='t1'; +select * from mysql.table_stats where db_name='db2' and table_name='t1'; + + +--echo # +--echo # Now, try with more than one column and with indexes: +--echo # +use test; +create table t1(a int primary key); +insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); + + +use db1; +create table t2 (a int, b int, c int, key IDX1(a), key IDX2(a,b)); +insert into t2 select a/10, a/2, a from test.t1; +analyze table t2 persistent for all; + +alter table t2 rename db2.t2; + +--echo # Verify that stats in the old database are gone: +select * from mysql.table_stats where db_name='db1' and table_name='t2'; +select * from mysql.column_stats where db_name='db1' and table_name='t2'; +select * from mysql.index_stats where db_name='db1' and table_name='t2'; + +--echo # Verify that stats are present in the new database: +select * from mysql.table_stats where db_name='db2' and table_name='t2'; +select * from mysql.column_stats where db_name='db2' and table_name='t2'; +select * from mysql.index_stats where db_name='db2' and table_name='t2'; + +use db2; +--echo # +--echo # Now, rename within the same database and verify: +--echo # +rename table t2 to t3; +--echo # No stats under old name: +select * from mysql.table_stats where db_name='db2' and table_name='t2'; +select * from mysql.column_stats where db_name='db2' and table_name='t2'; +select * from mysql.index_stats where db_name='db2' and table_name='t2'; +--echo # Stats under the new name: +select * from mysql.table_stats where db_name='db2' and table_name='t3'; +select * from mysql.column_stats where db_name='db2' and table_name='t3'; +select * from mysql.index_stats where db_name='db2' and table_name='t3'; + +use test; +drop database db1; +drop database db2; +drop table t1; + set use_stat_tables=@save_use_stat_tables; diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index 6496e1895fb..e0fd7005cd5 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -274,8 +274,9 @@ do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name, LEX_STRING table_name= { ren_table->table_name, ren_table->table_name_length }; LEX_STRING new_table= { (char *) new_alias, strlen(new_alias) }; + LEX_STRING new_db_name= { (char*)new_db, strlen(new_db)}; (void) rename_table_in_stat_tables(thd, &db_name, &table_name, - &db_name, &new_table); + &new_db_name, &new_table); if ((rc= Table_triggers_list::change_table_name(thd, ren_table->db, old_alias, ren_table->table_name, diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index c2150ba9309..e86c84040b4 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -592,6 +592,8 @@ public: stat_file->extra(HA_EXTRA_FLUSH); return FALSE; } + + friend class Stat_table_write_iter; }; @@ -1264,6 +1266,117 @@ public: }; + +/* + An iterator to enumerate statistics table rows which allows to modify + the rows while reading them. + + Used by RENAME TABLE handling to assign new dbname.tablename to statistic + rows. +*/ +class Stat_table_write_iter +{ + Stat_table *owner; + IO_CACHE io_cache; + uchar *rowid_buf; + uint rowid_size; + +public: + Stat_table_write_iter(Stat_table *stat_table_arg) + : owner(stat_table_arg), rowid_buf(NULL), + rowid_size(owner->stat_file->ref_length) + { + my_b_clear(&io_cache); + } + + /* + Initialize the iterator. It will return rows with n_keyparts matching the + curernt values. + + @return false - OK + true - Error + */ + bool init(uint n_keyparts) + { + if (!(rowid_buf= (uchar*)my_malloc(rowid_size, MYF(0)))) + return true; + + if (open_cached_file(&io_cache, mysql_tmpdir, TEMP_PREFIX, + 1024, MYF(MY_WME))) + return true; + + handler *h= owner->stat_file; + uchar key[MAX_KEY_LENGTH]; + uint prefix_len= 0; + for (uint i= 0; i < n_keyparts; i++) + prefix_len += owner->stat_key_info->key_part[i].store_length; + + key_copy(key, owner->record[0], owner->stat_key_info, + prefix_len); + key_part_map prefix_map= (key_part_map) ((1 << n_keyparts) - 1); + h->ha_index_init(owner->stat_key_idx, false); + int res= h->ha_index_read_map(owner->record[0], key, prefix_map, + HA_READ_KEY_EXACT); + if (res) + { + reinit_io_cache(&io_cache, READ_CACHE, 0L, 0, 0); + /* "Key not found" is not considered an error */ + return (res == HA_ERR_KEY_NOT_FOUND)? false: true; + } + + do { + h->position(owner->record[0]); + my_b_write(&io_cache, h->ref, rowid_size); + + } while (!h->ha_index_next_same(owner->record[0], key, prefix_len)); + + /* Prepare for reading */ + reinit_io_cache(&io_cache, READ_CACHE, 0L, 0, 0); + h->ha_index_or_rnd_end(); + if (h->ha_rnd_init(false)) + return true; + + return false; + } + + /* + Read the next row. + + @return + false OK + true No more rows or error. + */ + bool get_next_row() + { + if (!my_b_inited(&io_cache) || my_b_read(&io_cache, rowid_buf, rowid_size)) + return true; /* No more data */ + + handler *h= owner->stat_file; + /* + We should normally be able to find the row that we have rowid for. If we + don't, let's consider this an error. + */ + int res= h->ha_rnd_pos(owner->record[0], rowid_buf); + + return (res==0)? false : true; + } + + void cleanup() + { + if (rowid_buf) + my_free(rowid_buf); + rowid_buf= NULL; + owner->stat_file->ha_index_or_rnd_end(); + close_cached_file(&io_cache); + my_b_clear(&io_cache); + } + + ~Stat_table_write_iter() + { + cleanup(); + } +}; + /* Histogram_builder is a helper class that is used to build histograms for columns @@ -3285,25 +3398,34 @@ int rename_table_in_stat_tables(THD *thd, LEX_STRING *db, LEX_STRING *tab, stat_table= tables[INDEX_STAT].table; Index_stat index_stat(stat_table, db, tab); index_stat.set_full_table_name(); - while (index_stat.find_next_stat_for_prefix(2)) + + Stat_table_write_iter index_iter(&index_stat); + if (index_iter.init(2)) + rc= 1; + while (!index_iter.get_next_row()) { err= index_stat.update_table_name_key_parts(new_db, new_tab); if (err & !rc) rc= 1; index_stat.set_full_table_name(); } + index_iter.cleanup(); /* Rename table in the statistical table column_stats */ stat_table= tables[COLUMN_STAT].table; Column_stat column_stat(stat_table, db, tab); column_stat.set_full_table_name(); - while (column_stat.find_next_stat_for_prefix(2)) + Stat_table_write_iter column_iter(&column_stat); + if (column_iter.init(2)) + rc= 1; + while (!column_iter.get_next_row()) { err= column_stat.update_table_name_key_parts(new_db, new_tab); if (err & !rc) rc= 1; column_stat.set_full_table_name(); } + column_iter.cleanup(); /* Rename table in the statistical table table_stats */ stat_table= tables[TABLE_STAT].table; From 2553f143fdeb9068eb02a8fda58750c24071f5ef Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 19 Nov 2015 10:17:40 +0100 Subject: [PATCH 67/67] fix feedback plugin not to crash in debug builds feedback was bzero-ing thd->status_vars.memory_used, but server was asserting the correct value of it --- plugin/feedback/sender_thread.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/feedback/sender_thread.cc b/plugin/feedback/sender_thread.cc index 415c1f2e3c2..5114fd48726 100644 --- a/plugin/feedback/sender_thread.cc +++ b/plugin/feedback/sender_thread.cc @@ -260,7 +260,7 @@ ret: the effect of the background thread on SHOW STATUS. */ mysql_mutex_lock(&LOCK_thread_count); - bzero(&thd->status_var, sizeof(thd->status_var)); + thd->set_status_var_init(); thread_count--; thd->killed= KILL_CONNECTION; mysql_cond_broadcast(&COND_thread_count);