From e619295e1b480a24ee9740641ce69b8a412e1fc9 Mon Sep 17 00:00:00 2001 From: Sujatha Sivakumar Date: Tue, 28 Feb 2017 10:00:51 +0530 Subject: Bug#24901077: RESET SLAVE ALL DOES NOT ALWAYS RESET SLAVE Description: ============ If you have a relay log index file that has ended up with some relay log files that do not exists, then RESET SLAVE ALL is not enough to get back to a clean state. Analysis: ========= In the bug scenario slave server is in stopped state and some of the relay logs got deleted but the relay log index file is not updated. During slave server restart replication initialization fails as some of the required relay logs are missing. User executes RESET SLAVE/RESET SLAVE ALL command to start a clean slave. As per the documentation RESET SLAVE command clears the master info and relay log info repositories, deletes all the relay log files, and starts a new relay log file. But in a scenario where the slave server's Relay_log_info object is not initialized slave will not purge the existing relay logs. Hence the index file still remains in a bad state. Users will not be able to start the slave unless these files are cleared. Fix: === RESET SLAVE/RESET SLAVE ALL commands should do the cleanup even in a scenario where Relay_log_info object initialization failed. Backported a flag named 'error_on_rli_init_info' which is required to identify slave's Relay_log_info object initialization failure. This flag exists in MySQL-5.6 onwards as part of BUG#14021292 fix. During RESET SLAVE/RESET SLAVE ALL execution this flag indicates the Relay_log_info initialization failure. In such a case open the relay log index/relay log files and do the required clean up. --- sql/rpl_mi.cc | 3 +-- sql/rpl_rli.cc | 50 +++++++++++++++++++++++++++++++++++++++++--------- sql/rpl_rli.h | 11 +++++++++-- sql/slave.cc | 4 +++- sql/sql_repl.cc | 3 ++- 5 files changed, 56 insertions(+), 15 deletions(-) (limited to 'sql') diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index ee5caced11a..a78b31cbaed 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved. 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 @@ -551,7 +551,6 @@ void end_master_info(Master_info* mi) if (!mi->inited) DBUG_VOID_RETURN; - end_relay_log_info(&mi->rli); if (mi->fd >= 0) { end_io_cache(&mi->file); diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index e4f2e4fd382..65ab264e1f3 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved. 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 @@ -41,7 +41,8 @@ Relay_log_info::Relay_log_info(bool is_slave_recovery) no_storage(FALSE), replicate_same_server_id(::replicate_same_server_id), info_fd(-1), cur_log_fd(-1), relay_log(&sync_relaylog_period), sync_counter(0), is_relay_log_recovery(is_slave_recovery), - save_temporary_tables(0), cur_log_old_open_count(0), group_relay_log_pos(0), + save_temporary_tables(0), cur_log_old_open_count(0), + error_on_rli_init_info(false), group_relay_log_pos(0), event_relay_log_pos(0), #if HAVE_purify is_fake(FALSE), @@ -108,7 +109,7 @@ int init_relay_log_info(Relay_log_info* rli, const char* info_fname) { char fname[FN_REFLEN+128]; - int info_fd; + int info_fd= -1; const char* msg = 0; int error = 0; DBUG_ENTER("init_relay_log_info"); @@ -118,6 +119,8 @@ int init_relay_log_info(Relay_log_info* rli, DBUG_RETURN(0); fn_format(fname, info_fname, mysql_data_home, "", 4+32); mysql_mutex_lock(&rli->data_lock); + if (rli->error_on_rli_init_info) + goto err; info_fd = rli->info_fd; rli->cur_log_fd = -1; rli->slave_skip_counter=0; @@ -351,11 +354,14 @@ Failed to open the existing relay log info file '%s' (errno %d)", goto err; } rli->inited= 1; + rli->error_on_rli_init_info= false; mysql_mutex_unlock(&rli->data_lock); DBUG_RETURN(error); err: - sql_print_error("%s", msg); + rli->error_on_rli_init_info= true; + if (msg) + sql_print_error("%s", msg); end_io_cache(&rli->info_file); if (info_fd >= 0) mysql_file_close(info_fd, MYF(0)); @@ -942,6 +948,8 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset, const char** errmsg) { int error=0; + const char *ln; + char name_buf[FN_REFLEN]; DBUG_ENTER("purge_relay_logs"); /* @@ -968,12 +976,34 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset, if (!rli->inited) { DBUG_PRINT("info", ("rli->inited == 0")); - DBUG_RETURN(0); - } - - DBUG_ASSERT(rli->slave_running == 0); - DBUG_ASSERT(rli->mi->slave_running == 0); + if (rli->error_on_rli_init_info) + { + ln= rli->relay_log.generate_name(opt_relay_logname, "-relay-bin", + 1, name_buf); + if (rli->relay_log.open_index_file(opt_relaylog_index_name, ln, TRUE)) + { + sql_print_error("Unable to purge relay log files. Failed to open relay " + "log index file:%s.", rli->relay_log.get_index_fname()); + DBUG_RETURN(1); + } + if (rli->relay_log.open(ln, LOG_BIN, 0, SEQ_READ_APPEND, 0, + (max_relay_log_size ? max_relay_log_size : + max_binlog_size), 1, TRUE)) + { + sql_print_error("Unable to purge relay log files. Failed to open relay " + "log file:%s.", rli->relay_log.get_log_fname()); + DBUG_RETURN(1); + } + } + else + DBUG_RETURN(0); + } + else + { + DBUG_ASSERT(rli->slave_running == 0); + DBUG_ASSERT(rli->mi->slave_running == 0); + } rli->slave_skip_counter=0; mysql_mutex_lock(&rli->data_lock); @@ -1013,6 +1043,8 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset, rli->group_relay_log_pos, 0 /* do not need data lock */, errmsg, 0); + if (!rli->inited && rli->error_on_rli_init_info) + rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT); err: #ifndef DBUG_OFF char buf[22]; diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h index dceeec9e777..89865a9f55c 100644 --- a/sql/rpl_rli.h +++ b/sql/rpl_rli.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. 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 @@ -153,7 +153,14 @@ public: a different log under our feet */ uint32 cur_log_old_open_count; - + + /* + If on init_info() call error_on_rli_init_info is true that means + that previous call to init_info() terminated with an error, RESET + SLAVE must be executed and the problem fixed manually. + */ + bool error_on_rli_init_info; + /* Let's call a group (of events) : - a transaction diff --git a/sql/slave.cc b/sql/slave.cc index acf68e231f3..1e641ac6d7e 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. 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 @@ -881,6 +881,7 @@ void close_active_mi() if (active_mi) { end_master_info(active_mi); + end_relay_log_info(&active_mi->rli); delete active_mi; active_mi= 0; } @@ -4165,6 +4166,7 @@ void end_relay_log_info(Relay_log_info* rli) { DBUG_ENTER("end_relay_log_info"); + rli->error_on_rli_init_info= false; if (!rli->inited) DBUG_VOID_RETURN; if (rli->info_fd >= 0) diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 8bbb8c52d95..ecbeff87a61 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. 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 @@ -1313,6 +1313,7 @@ int reset_slave(THD *thd, Master_info* mi) // close master_info_file, relay_log_info_file, set mi->inited=rli->inited=0 end_master_info(mi); + end_relay_log_info(&mi->rli); // and delete these two files fn_format(fname, master_info_file, mysql_data_home, "", 4+32); if (mysql_file_stat(key_file_master_info, fname, &stat_area, MYF(0)) && -- cgit v1.2.1 From af84921d263b8bb1d1a06989794db07394f94e21 Mon Sep 17 00:00:00 2001 From: Karthik Kamath Date: Thu, 9 Mar 2017 14:57:20 +0530 Subject: BUG#24807826: UINT3KORR SHOULD STOP READING FOUR INSTEAD OF THREE BYTES ON X86 Analysis: ========= The macro uint3korr reads 4 bytes of data instead of 3 on on x86 machines. Multiple definitions were created for this macro for optimization in WIN32. The idea was to optimize reading of 3 byte ints by reading an ordinary int and masking away the unused byte. However this is an undefined behavior. It will be an issue unless users are aware of allocating an extra byte for using this macro. Fix: ==== Removing the definition which reads 4 bytes of data. The only definition of this macro would now read just 3 bytes of data thus prohibiting the usage of an extra byte. Note: ===== This is a backport of Patches #5 and #6 for Bug#17922198. --- sql/net_serv.cc | 15 ++++++--------- sql/records.cc | 5 ++--- 2 files changed, 8 insertions(+), 12 deletions(-) (limited to 'sql') diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 9c0c84bb292..b2c36f7c29c 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. 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 @@ -179,12 +179,10 @@ my_bool net_realloc(NET *net, size_t length) pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1); /* We must allocate some extra bytes for the end 0 and to be able to - read big compressed blocks + 1 safety byte since uint3korr() in - my_real_read() may actually read 4 bytes depending on build flags and - platform. + read big compressed blocks in my_real_read(). */ if (!(buff= (uchar*) my_realloc((char*) net->buff, pkt_length + - NET_HEADER_SIZE + COMP_HEADER_SIZE + 1, + NET_HEADER_SIZE + COMP_HEADER_SIZE, MYF(MY_WME)))) { /* @todo: 1 and 2 codes are identical. */ @@ -951,12 +949,11 @@ my_real_read(NET *net, size_t *complen) if (net->compress) { /* - The following uint3korr() may read 4 bytes, so make sure we don't - read unallocated or uninitialized memory. The right-hand expression - must match the size of the buffer allocated in net_realloc(). + The right-hand expression must match the size of the buffer + allocated in net_realloc(). */ DBUG_ASSERT(net->where_b + NET_HEADER_SIZE + sizeof(uint32) <= - net->max_packet + NET_HEADER_SIZE + COMP_HEADER_SIZE + 1); + net->max_packet + NET_HEADER_SIZE + COMP_HEADER_SIZE); /* If the packet is compressed then complen > 0 and contains the number of bytes in the uncompressed packet diff --git a/sql/records.cc b/sql/records.cc index 7f74b84b2d7..ae7ec74c17d 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. 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 @@ -589,10 +589,9 @@ static int init_rr_cache(THD *thd, READ_RECORD *info) rec_cache_size= info->cache_records*info->reclength; info->rec_cache_size= info->cache_records*info->ref_length; - // We have to allocate one more byte to use uint3korr (see comments for it) if (info->cache_records <= 2 || !(info->cache=(uchar*) my_malloc_lock(rec_cache_size+info->cache_records* - info->struct_length+1, + info->struct_length, MYF(0)))) DBUG_RETURN(1); #ifdef HAVE_purify -- cgit v1.2.1 From fc4c53c28899abf5547e0e0a89b4d91645250895 Mon Sep 17 00:00:00 2001 From: Karthik Kamath Date: Fri, 10 Mar 2017 22:34:38 +0530 Subject: BUG#24807826: UINT3KORR SHOULD STOP READING FOUR INSTEAD OF THREE BYTES ON X86 Post push fix for resolving main.archive test failure in valgrind. --- sql/records.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/records.cc b/sql/records.cc index ae7ec74c17d..14a4390b229 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -596,7 +596,7 @@ static int init_rr_cache(THD *thd, READ_RECORD *info) DBUG_RETURN(1); #ifdef HAVE_purify // Avoid warnings in qsort - bzero(info->cache,rec_cache_size+info->cache_records* info->struct_length+1); + bzero(info->cache,rec_cache_size+info->cache_records* info->struct_length); #endif DBUG_PRINT("info",("Allocated buffert for %d records",info->cache_records)); info->read_positions=info->cache+rec_cache_size; -- cgit v1.2.1 From 3c6c0ebc6a31835260d07463d581b9715776812f Mon Sep 17 00:00:00 2001 From: Nisha Gopalakrishnan Date: Mon, 9 Jan 2017 20:09:57 +0530 Subject: BUG#25250768: WRITING ON A READ_ONLY=ON SERVER WITHOUT SUPER PRIVILEGE. Backport from mysql-5.7 to mysql-5.5 and mysql-5.6. BUG#13969578: TEMPORARY TABLE IN A DATABASE ON A READ-ONLY INSTANCE CAN BE OVERWRITTEN Analysis: ======== Creation or modification of a persistent table by a non-super user is NOT ALLOWED in read_only mode. Only TEMPORARY tables are allowed to be created or modified in read_only mode. But the creation of a persistent table was being allowed when a temporary table of the same name existed. The routine which denies updating a non-temporary table in a read_only mode does not handle the case of creation of a regular table when a temporary table of the same exists. Fix: === Handled the condition where an attempt is made to create a persistent table having the same name as that of the temporary table. Hence the creation of a persistent table by a non-super user when a temporary table of the same exists is denied under read_only mode. --- sql/sql_parse.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'sql') diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 86763b6e3de..82ab76b2e1c 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -822,14 +822,18 @@ static my_bool deny_updates_if_read_only_option(THD *thd, (lex->sql_command == SQLCOM_CREATE_TABLE) && (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE); + const my_bool create_real_tables= + (lex->sql_command == SQLCOM_CREATE_TABLE) && + !(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE); + const my_bool drop_temp_tables= (lex->sql_command == SQLCOM_DROP_TABLE) && lex->drop_temporary; const my_bool update_real_tables= - some_non_temp_table_to_be_updated(thd, all_tables) && - !(create_temp_tables || drop_temp_tables); - + ((create_real_tables || + some_non_temp_table_to_be_updated(thd, all_tables)) && + !(create_temp_tables || drop_temp_tables)); const my_bool create_or_drop_databases= (lex->sql_command == SQLCOM_CREATE_DB) || -- cgit v1.2.1 From 3b562dcf6e5423d41d41ef416c18187c3a946d9e Mon Sep 17 00:00:00 2001 From: Shishir Jaiswal Date: Tue, 16 May 2017 13:48:52 +0530 Subject: Bug#16212207 - LOAD XML INFILE PERFORMANCE WITH INDENTED XML DESCRIPTION =========== LOAD XML INFILE performance becomes painfully slow if the tags' value has any space(s) in between them. They're usually kept intentionally for indentation purpose. ANALYSIS ======== The extra spaces are calling clear_level() many a times which is having overhead of clearing taglist etc. This can be avoided altogether by skipping all such spaces. FIX === Trim all the starting whitespaces from the value before passing it to read_value() --- sql/sql_load.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/sql_load.cc b/sql/sql_load.cc index c28c7cdb2db..a2c01c3b8a8 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. 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 @@ -1989,6 +1989,13 @@ int READ_INFO::read_xml() case '>': /* end tag - read tag value */ in_tag= false; + /* Skip all whitespaces */ + while (' ' == (chr= my_tospace(GET))); + /* + Push the first non-whitespace char back to Stack. This char would be + read in the upcoming call to read_value() + */ + PUSH(chr); chr= read_value('<', &value); if(chr == my_b_EOF) goto found_eof; -- cgit v1.2.1 From 8c7e9aab054360ec192ce3cffb2c25aa16e25f10 Mon Sep 17 00:00:00 2001 From: Shishir Jaiswal Date: Tue, 23 May 2017 10:22:33 +0530 Subject: Bug#16212207 - LOAD XML INFILE PERFORMANCE WITH INDENTED XML Post-push fix for build failure on Linux machine sles11-x86-64bit --- sql/sql_load.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/sql_load.cc b/sql/sql_load.cc index a2c01c3b8a8..6d6dc8b55e8 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -1990,7 +1990,9 @@ int READ_INFO::read_xml() case '>': /* end tag - read tag value */ in_tag= false; /* Skip all whitespaces */ - while (' ' == (chr= my_tospace(GET))); + while (' ' == (chr= my_tospace(GET))) + { + } /* Push the first non-whitespace char back to Stack. This char would be read in the upcoming call to read_value() -- cgit v1.2.1 From c34f2e518a141ac117eaa4d08ca283d4440752b6 Mon Sep 17 00:00:00 2001 From: Sreeharsha Ramanavarapu Date: Wed, 24 May 2017 08:50:05 +0530 Subject: Bug #24595639: INCORRECT BEHAVIOR IN QUERY WITH UNION AND GROUP BY Issue 1: -------- This problem occurs in the following conditions: 1) A UNION is present in the subquery of select list and handles multiple columns. 2) Query has a GROUP BY. A temporary table is created to handle the UNION. Item_field objects are based on the expressions of the result of the UNION (ie. the fake_select_lex). While checking validity of the columns in the GROUP BY list, the columns of the temporary table are checked in Item_ident::local_column. But the Item_field objects created for the temporary table don't have information like the Name_resolution_context that they belong to or whether they are dependent on an outer query. Since these members are null, incorrect behavior is caused. This can happen when such Item objects are cached to apply the IN-to-EXISTS transform for Item_row. Solution to Issue 1: -------------------- Context information of the first select in the UNION will be assigned to the new Item_field objects. Issue 2: -------- This problem occurs in the following conditions: 1) A UNION is present in the subquery of select list. 2) A column in the UNION's first SELECT refers to a table in the outer-query making it a dependent union. 3) GROUP BY column refers to the outer-referencing column. While resolving the select list with an outer-reference, an Item_outer_ref object is created to handle the outer-query's GROUP BY list. The Item_outer_ref object replaces the Item_field object in the item tree. Item_outer_ref::fix_fields will be called only while fixing the inner references of the outer query. Before resolving the outer-query, an Item_type_holder object needs to be created to handle the UNION. But as explained above, the Item_outer_ref object has not been fixed yet. Having a fixed Item object is a pre-condition for creating an Item_type_holder. Solution to Issue 2: -------------------- Use the reference (real_item()) of an Item_outer_ref object instead of the object itself while creating an Item_type_holder. --- sql/item.cc | 5 ++++- sql/sql_union.cc | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/item.cc b/sql/item.cc index 34157c33cf4..6f1fdaae398 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. 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 @@ -1949,6 +1949,9 @@ Item_field::Item_field(Field *f) item_equal(0), no_const_subst(0), have_privileges(0), any_privileges(0) { + if (f->table->pos_in_table_list != NULL) + context= &(f->table->pos_in_table_list->select_lex->context); + set_field(f); /* field_name and table_name should not point to garbage diff --git a/sql/sql_union.cc b/sql/sql_union.cc index d230b903d2c..ca6870dab9c 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. 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 @@ -282,6 +282,19 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, Item *item_tmp; while ((item_tmp= it++)) { + /* + If the outer query has a GROUP BY clause, an outer reference to this + query block may have been wrapped in a Item_outer_ref, which has not + been fixed yet. An Item_type_holder must be created based on a fixed + Item, so use the inner Item instead. + */ + DBUG_ASSERT(item_tmp->fixed || + (item_tmp->type() == Item::REF_ITEM && + ((Item_ref *)(item_tmp))->ref_type() == + Item_ref::OUTER_REF)); + if (!item_tmp->fixed) + item_tmp= item_tmp->real_item(); + /* Error's in 'new' will be detected after loop */ types.push_back(new Item_type_holder(thd_arg, item_tmp)); } -- cgit v1.2.1 From a06f2f430f6cfd55929c3734b24e04fa70803156 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Tue, 14 Mar 2017 16:35:39 +0400 Subject: MDEV-12078 Using spatial index changes type from point to geometry In get_mm_tree we have to change Field_geom::geom_type to GEOMETRY as we have to let storing all types of the spatial features in the field. So now we restore the original geom_type as it's done. --- sql/opt_range.cc | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'sql') diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 481d8445fa8..3563058282b 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -7949,8 +7949,10 @@ static SEL_TREE *get_full_func_mm_tree(RANGE_OPT_PARAM *param, DBUG_ENTER("get_full_func_mm_tree"); #ifdef HAVE_SPATIAL + Field::geometry_type sav_geom_type; if (field_item->field->type() == MYSQL_TYPE_GEOMETRY) { + sav_geom_type= ((Field_geom*) field_item->field)->geom_type; /* We have to be able to store all sorts of spatial features here */ ((Field_geom*) field_item->field)->geom_type= Field::GEOM_GEOMETRY; } @@ -7982,6 +7984,13 @@ static SEL_TREE *get_full_func_mm_tree(RANGE_OPT_PARAM *param, } } } + +#ifdef HAVE_SPATIAL + if (field_item->field->type() == MYSQL_TYPE_GEOMETRY) + { + ((Field_geom*) field_item->field)->geom_type= sav_geom_type; + } +#endif /*HAVE_SPATIAL*/ DBUG_RETURN(ftree); } -- cgit v1.2.1 From c5975eaea174460e774e77717e972a8d32e6c8de Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 12 Jul 2017 08:05:42 +0200 Subject: MDEV-7339 Server crashes in Item_func_trig_cond::val_int Item_in_subselect::pushed_cond_guards[] array is allocated only when left_expr->maybe_null. And it is used (for row expressions) when left_expr->element_index(i)->maybe_null. For left_expr being a multi-column subquery, its maybe_null is always false when the subquery doesn't use tables (see Item_singlerow_subselect::fix_length_and_dec() and subselect_single_select_engine::fix_length_and_dec()), otherwise it's always true. But row elements can be NULL regardless, so let's always allocate pushed_cond_guards for multi-column subqueries, no matter whether its maybe_null was forced to true or false. --- sql/item_subselect.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index e0da946d190..068f32c99b9 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -2871,7 +2871,8 @@ bool Item_in_subselect::init_cond_guards() { DBUG_ASSERT(thd); uint cols_num= left_expr->cols(); - if (!abort_on_null && left_expr->maybe_null && !pushed_cond_guards) + if (!abort_on_null && !pushed_cond_guards && + (left_expr->maybe_null || cols_num > 1)) { if (!(pushed_cond_guards= (bool*)thd->alloc(sizeof(bool) * cols_num))) return TRUE; -- cgit v1.2.1 From be55bbc2b206f2fe295ad4179b23791c3119fe02 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 12 Jul 2017 12:49:29 +0200 Subject: MDEV-7826 Server crashes in Item_subselect::enumerate_field_refs_processor upper->item can be NULL if we're referring to an aggregate function --- sql/item_subselect.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 068f32c99b9..ef90dd59be3 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -316,7 +316,8 @@ bool Item_subselect::enumerate_field_refs_processor(uchar *arg) while ((upper= it++)) { - if (upper->item->walk(&Item::enumerate_field_refs_processor, FALSE, arg)) + if (upper->item && + upper->item->walk(&Item::enumerate_field_refs_processor, FALSE, arg)) return TRUE; } return FALSE; -- cgit v1.2.1 From c83d6ff881dcfd1cc68124a9663c2a31ca7e2dce Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 12 Jul 2017 13:55:04 +0200 Subject: compiler warning remove unused variable --- sql/item.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'sql') diff --git a/sql/item.cc b/sql/item.cc index 68411860274..61ad4bdb853 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -5048,7 +5048,6 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) if (thd->lex->in_sum_func && thd->lex->in_sum_func->nest_level >= select->nest_level) { - Item::Type ref_type= (*reference)->type(); set_if_bigger(thd->lex->in_sum_func->max_arg_level, select->nest_level); } -- cgit v1.2.1 From 05b678bc8c166c9015ca3dc3ccd9e9c89094f3ca Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 12 Jul 2017 14:21:41 +0200 Subject: MDEV-12489 The select stmt may fail due to "having clause is ambiguous" unexpected only compare field references with an alias (from the SELECT clause) when this reference doesn't specify an explicit table name part. --- sql/item.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/item.cc b/sql/item.cc index 61ad4bdb853..b7dac96d418 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4622,7 +4622,7 @@ static Item** find_field_in_group_list(Item *find_item, ORDER *group_list) int cur_match_degree= 0; /* SELECT list element with explicit alias */ - if ((*(cur_group->item))->name && + if ((*(cur_group->item))->name && !table_name && !(*(cur_group->item))->is_autogenerated_name && !my_strcasecmp(system_charset_info, (*(cur_group->item))->name, field_name)) -- cgit v1.2.1 From e7f51e5d269ba8adb917226724564274a57d07b3 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 12 Jul 2017 19:20:52 +0200 Subject: MDEV-12136 SELECT COUNT(DISTINCT) returns the wrong value when tmp_table_size is limited use the correct value for the merge_buffer size, max_in_memory_size is too small and merge_walk() fails. also: remove a cast. --- sql/uniques.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sql') diff --git a/sql/uniques.cc b/sql/uniques.cc index fe3e329cda6..f80117065dd 100644 --- a/sql/uniques.cc +++ b/sql/uniques.cc @@ -461,7 +461,7 @@ C_MODE_END <> 0 error */ -static bool merge_walk(uchar *merge_buffer, ulong merge_buffer_size, +static bool merge_walk(uchar *merge_buffer, size_t merge_buffer_size, uint key_length, BUFFPEK *begin, BUFFPEK *end, tree_walk_action walk_action, void *walk_action_arg, qsort_cmp2 compare, void *compare_arg, @@ -470,7 +470,7 @@ static bool merge_walk(uchar *merge_buffer, ulong merge_buffer_size, BUFFPEK_COMPARE_CONTEXT compare_context = { compare, compare_arg }; QUEUE queue; if (end <= begin || - merge_buffer_size < (ulong) (key_length * (end - begin + 1)) || + merge_buffer_size < (size_t) (key_length * (end - begin + 1)) || init_queue(&queue, (uint) (end - begin), offsetof(BUFFPEK, key), 0, buffpek_compare, &compare_context, 0, 0)) return 1; @@ -615,7 +615,7 @@ bool Unique::walk(TABLE *table, tree_walk_action action, void *walk_action_arg) if (!res) { - res= merge_walk(merge_buffer, (ulong) max_in_memory_size, full_size, + res= merge_walk(merge_buffer, buff_sz, full_size, (BUFFPEK *) file_ptrs.buffer, (BUFFPEK *) file_ptrs.buffer + file_ptrs.elements, action, walk_action_arg, -- cgit v1.2.1 From 27bc13b7a2f99a6011a5081670b320c685dde443 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 12 Jul 2017 19:31:01 +0200 Subject: MDEV-12136 SELECT COUNT(DISTINCT) returns the wrong value when tmp_table_size is limited Same MDEV, second bug. Merge buffer must fit at least MERGEBUFF2 (that is, 15) key values. Because merge_index() can merge that many buffers, and merge_many_buff() leaves that many buffers unmerged. --- sql/uniques.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/uniques.cc b/sql/uniques.cc index f80117065dd..8b7da7e6e52 100644 --- a/sql/uniques.cc +++ b/sql/uniques.cc @@ -607,11 +607,15 @@ bool Unique::walk(TABLE *table, tree_walk_action action, void *walk_action_arg) return 1; if (flush_io_cache(&file) || reinit_io_cache(&file, READ_CACHE, 0L, 0, 0)) return 1; - size_t buff_sz= (max_in_memory_size / full_size + 1) * full_size; + /* + merge_buffer must fit at least MERGEBUFF2 keys, because + merge_index() can merge that many BUFFPEKs at once. + */ + size_t buff_sz= max(MERGEBUFF2, max_in_memory_size/full_size+1) * full_size; if (!(merge_buffer = (uchar *)my_malloc(buff_sz, MYF(MY_WME)))) return 1; if (buff_sz < (ulong) (full_size * (file_ptrs.elements + 1))) - res= merge(table, merge_buffer, buff_sz >= full_size * MERGEBUFF2) ; + res= merge(table, merge_buffer, true) ; if (!res) { -- cgit v1.2.1 From 7e44eabdad59993c504699e01d15ddb106f64e9b Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Tue, 18 Jul 2017 13:19:34 +0400 Subject: MDEV-11205 UDF_ARGS "attribute_lengths" incorrect value. Set name_length properly in Item_idnet constructors. --- sql/item.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sql') diff --git a/sql/item.cc b/sql/item.cc index b7dac96d418..dff2f3d3ee6 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -817,6 +817,7 @@ Item_ident::Item_ident(Name_resolution_context *context_arg, cached_table(0), depended_from(0), can_be_depended(TRUE) { name = (char*) field_name_arg; + name_length= name ? strlen(name) : 0; } @@ -829,6 +830,7 @@ Item_ident::Item_ident(TABLE_LIST *view_arg, const char *field_name_arg) cached_table(NULL), depended_from(NULL), can_be_depended(TRUE) { name = (char*) field_name_arg; + name_length= name ? strlen(name) : 0; } -- cgit v1.2.1 From e7fd6ed3875bd91dbd30a62291ae471c35da8fdf Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Mon, 17 Jul 2017 22:34:07 +0200 Subject: MDEV-11240: Server crashes in check_view_single_update or Assertion `derived->table' failed in mysql_derived_merge_for_insert Move table pointer for single table view (even if it is view over other view) to make the access universal. --- sql/sql_derived.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 20fca2de8cf..493f0eccc8c 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -525,7 +525,9 @@ bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived) derived->schema_table= derived->merge_underlying_list->schema_table; derived->merged_for_insert= TRUE; } - } + } + else + derived->table= derived->merge_underlying_list->table; DBUG_RETURN(FALSE); } -- cgit v1.2.1 From 9b3360ea4417ed653d5c7eed29f4ef7e80618e43 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 18 Jul 2017 14:47:40 +0200 Subject: BUG#25250768: WRITING ON A READ_ONLY=ON SERVER WITHOUT SUPER PRIVILEGE simplify. add a test case. --- sql/sql_parse.cc | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) (limited to 'sql') diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 83cd6cccba5..1d596ed9df7 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -835,24 +835,16 @@ static my_bool deny_updates_if_read_only_option(THD *thd, if (lex->sql_command == SQLCOM_UPDATE_MULTI) DBUG_RETURN(FALSE); - const my_bool create_temp_tables= - (lex->sql_command == SQLCOM_CREATE_TABLE) && - (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE); - - const my_bool create_real_tables= - (lex->sql_command == SQLCOM_CREATE_TABLE) && - !(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE); - - const my_bool drop_temp_tables= - (lex->sql_command == SQLCOM_DROP_TABLE) && - lex->drop_temporary; - - const my_bool update_real_tables= - ((create_real_tables || - some_non_temp_table_to_be_updated(thd, all_tables)) && - !(create_temp_tables || drop_temp_tables)); + /* + a table-to-be-created is not in the temp table list yet, + so CREATE TABLE needs a special treatment + */ + const bool update_real_tables= + lex->sql_command == SQLCOM_CREATE_TABLE + ? !(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) + : some_non_temp_table_to_be_updated(thd, all_tables); - const my_bool create_or_drop_databases= + const bool create_or_drop_databases= (lex->sql_command == SQLCOM_CREATE_DB) || (lex->sql_command == SQLCOM_DROP_DB); -- cgit v1.2.1 From 172e3a1bc6ab1e38dd8be074b2c10cc734456e35 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Mon, 1 May 2017 18:34:11 +1000 Subject: MDEV-12646: Apply fixes found by Coverity static analysis tool Inspired by: https://github.com/devexp-db/mariadb/blob/f27/mariadb-covscan-stroverflow.patch --- sql/rpl_handler.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/rpl_handler.cc b/sql/rpl_handler.cc index 5b75d6c30ea..ca3b57edce3 100644 --- a/sql/rpl_handler.cc +++ b/sql/rpl_handler.cc @@ -260,7 +260,7 @@ int Binlog_storage_delegate::after_flush(THD *thd, thd->semisync_info= log_info; } - strcpy(log_info->log_file, log_file+dirname_length(log_file)); + strmake_buf(log_info->log_file, log_file+dirname_length(log_file)); log_info->log_pos = log_pos; FOREACH_OBSERVER(ret, after_flush, false, -- cgit v1.2.1 From 58aaae6f2a23e68b23727016844d177f178ea8ff Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 18 Jul 2017 16:42:40 +0200 Subject: ensure that filename in COM_BINLOG_DUMP isn't too long --- sql/sql_parse.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'sql') diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1d596ed9df7..ba0520de4bb 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1271,9 +1271,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd, kill_zombie_dump_threads(slave_server_id); thd->server_id = slave_server_id; - general_log_print(thd, command, "Log: '%s' Pos: %ld", packet+10, - (long) pos); - mysql_binlog_send(thd, thd->strdup(packet + 10), (my_off_t) pos, flags); + const char *name= packet + 10; + size_t nlen= strlen(name); + + general_log_print(thd, command, "Log: '%s' Pos: %lu", name, pos); + if (nlen < FN_REFLEN) + mysql_binlog_send(thd, thd->strmake(name, nlen), (my_off_t)pos, flags); unregister_slave(thd,1,1); /* fake COM_QUIT -- if we get here, the thread needs to terminate */ error = TRUE; -- cgit v1.2.1 From da2a838628796453c6ab93d51eca9e5aae45791d Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 19 Jul 2017 19:46:07 +0200 Subject: MDEV-12824 GCC 7 warning: this statement may fall through [-Wimplicit-fallthrough=] --- sql/item_func.cc | 5 +++-- sql/log.cc | 2 +- sql/sql_repl.cc | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'sql') diff --git a/sql/item_func.cc b/sql/item_func.cc index 13ea5291edc..0ca8f700bfc 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -848,8 +848,9 @@ void Item_func_num1::fix_length_and_dec() { DBUG_ENTER("Item_func_num1::fix_length_and_dec"); DBUG_PRINT("info", ("name %s", func_name())); - switch (cached_result_type= args[0]->cast_to_int_type()) { + switch (args[0]->cast_to_int_type()) { case INT_RESULT: + cached_result_type= INT_RESULT; max_length= args[0]->max_length; unsigned_flag= args[0]->unsigned_flag; break; @@ -860,8 +861,8 @@ void Item_func_num1::fix_length_and_dec() max_length= float_length(decimals); break; case TIME_RESULT: - cached_result_type= DECIMAL_RESULT; case DECIMAL_RESULT: + cached_result_type= DECIMAL_RESULT; decimals= args[0]->decimal_scale(); // Do not preserve NOT_FIXED_DEC max_length= args[0]->max_length; break; diff --git a/sql/log.cc b/sql/log.cc index 3cad1716ca4..ee92f22adb8 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -9405,8 +9405,8 @@ int TC_LOG_BINLOG::recover(LOG_INFO *linfo, const char *last_log_name, sizeof(xev->xid)); if (!x || my_hash_insert(&xids, x)) goto err2; - break; } + break; } case BINLOG_CHECKPOINT_EVENT: if (first_round && do_xa) diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index ebe89e2b4a0..0ddeeaa0266 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -2665,6 +2665,7 @@ impossible position"; loop_breaker = (flags & BINLOG_DUMP_NON_BLOCK); break; } + /* fall through */ default: errmsg = "could not find next log"; my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; -- cgit v1.2.1 From dc8b2fb03a5a2dff4687eb8dad042b34730b5210 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 19 Jul 2017 19:47:38 +0200 Subject: MDEV-11896 thd_get_error_context_description race condition Change the semantics of thd_get_error_context_description(). It no longer expects the caller to lock LOCK_thread_count (no caller ever did that anyway), but takes care of it internally. --- sql/sql_class.cc | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'sql') diff --git a/sql/sql_class.cc b/sql/sql_class.cc index bebdd82ea83..da1a0e43ac1 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -725,12 +725,6 @@ extern "C" @param buffer pointer to preferred result buffer @param length length of buffer @param max_query_len how many chars of query to copy (0 for all) - - @req LOCK_thread_count - - @note LOCK_thread_count mutex is not necessary when the function is invoked on - the currently running thread (current_thd) or if the caller in some other - way guarantees that access to thd->query is serialized. @return Pointer to string */ @@ -744,6 +738,9 @@ char *thd_get_error_context_description(THD *thd, char *buffer, const Security_context *sctx= &thd->main_security_ctx; char header[256]; int len; + + mysql_mutex_lock(&LOCK_thread_count); + /* The pointers thd->query and thd->proc_info might change since they are being modified concurrently. This is acceptable for proc_info since its @@ -799,6 +796,7 @@ char *thd_get_error_context_description(THD *thd, char *buffer, } mysql_mutex_unlock(&thd->LOCK_thd_data); } + mysql_mutex_unlock(&LOCK_thread_count); if (str.c_ptr_safe() == buffer) return buffer; -- cgit v1.2.1 From 2fcd8c12522f5f935066b661c42b5b7cb416d148 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 19 Jul 2017 22:22:14 +0200 Subject: MDEV-13173 An RLIKE that previously worked on 10.0 now returns "Got error 'pcre_exec: recursion limit of 100 exceeded' from regexp" 1. use Regexp_processor_pcre::set_recursion_limit() to set the recursion limit depending on the current available stack size 2. make pcre stack frame to be estimated no less than 500 bytes. sometimes pcre estimates it too low, even though the manual says 500+16 bytes (it was estimated only 188 for me, actual frame size was 512). 3. do it for embedded too --- sql/item_cmpfunc.cc | 15 ++++++++++++++- sql/item_cmpfunc.h | 2 ++ sql/item_strfunc.cc | 14 ++++++++++++++ sql/item_strfunc.h | 2 ++ sql/mysqld.cc | 10 ++++------ 5 files changed, 36 insertions(+), 7 deletions(-) (limited to 'sql') diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 038a0ebabc2..0134f628c80 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -5110,7 +5110,7 @@ void Regexp_processor_pcre::set_recursion_limit(THD *thd) DBUG_ASSERT(thd == current_thd); stack_used= available_stack_size(thd->thread_stack, &stack_used); m_pcre_extra.match_limit_recursion= - (my_thread_stack_size - stack_used)/my_pcre_frame_size; + (my_thread_stack_size - STACK_MIN_SIZE - stack_used)/my_pcre_frame_size; } @@ -5372,6 +5372,12 @@ void Regexp_processor_pcre::fix_owner(Item_func *owner, } +bool Item_func_regex::fix_fields(THD *thd, Item **ref) +{ + re.set_recursion_limit(thd); + return Item_bool_func::fix_fields(thd, ref); +} + void Item_func_regex::fix_length_and_dec() { @@ -5398,6 +5404,13 @@ longlong Item_func_regex::val_int() } +bool Item_func_regexp_instr::fix_fields(THD *thd, Item **ref) +{ + re.set_recursion_limit(thd); + return Item_int_func::fix_fields(thd, ref); +} + + void Item_func_regexp_instr::fix_length_and_dec() { diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 17ad1bd8c7d..ba0af32d76f 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1652,6 +1652,7 @@ public: DBUG_VOID_RETURN; } longlong val_int(); + bool fix_fields(THD *thd, Item **ref); void fix_length_and_dec(); const char *func_name() const { return "regexp"; } @@ -1679,6 +1680,7 @@ public: DBUG_VOID_RETURN; } longlong val_int(); + bool fix_fields(THD *thd, Item **ref); void fix_length_and_dec(); const char *func_name() const { return "regexp_instr"; } }; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 22e13bf6c38..c3043adac47 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1343,6 +1343,13 @@ void Item_func_replace::fix_length_and_dec() /*********************************************************************/ +bool Item_func_regexp_replace::fix_fields(THD *thd, Item **ref) +{ + re.set_recursion_limit(thd); + return Item_str_func::fix_fields(thd, ref); +} + + void Item_func_regexp_replace::fix_length_and_dec() { if (agg_arg_charsets_for_string_result_with_comparison(collation, args, 3)) @@ -1478,6 +1485,13 @@ err: } +bool Item_func_regexp_substr::fix_fields(THD *thd, Item **ref) +{ + re.set_recursion_limit(thd); + return Item_str_func::fix_fields(thd, ref); +} + + void Item_func_regexp_substr::fix_length_and_dec() { if (agg_arg_charsets_for_string_result_with_comparison(collation, args, 2)) diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 769bde67cb1..1b133d1d885 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -231,6 +231,7 @@ public: DBUG_VOID_RETURN; } String *val_str(String *str); + bool fix_fields(THD *thd, Item **ref); void fix_length_and_dec(); const char *func_name() const { return "regexp_replace"; } }; @@ -251,6 +252,7 @@ public: DBUG_VOID_RETURN; } String *val_str(String *str); + bool fix_fields(THD *thd, Item **ref); void fix_length_and_dec(); const char *func_name() const { return "regexp_substr"; } }; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 32cdda9debc..d9320fa3bcf 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3451,7 +3451,6 @@ sizeof(load_default_groups)/sizeof(load_default_groups[0]); #endif -#ifndef EMBEDDED_LIBRARY /** This function is used to check for stack overrun for pathological cases of regular expressions and 'like' expressions. @@ -3480,8 +3479,6 @@ check_enough_stack_size(int recurse_level) return 0; return check_enough_stack_size_slow(); } -#endif - /* @@ -3503,11 +3500,12 @@ static void init_pcre() { pcre_malloc= pcre_stack_malloc= my_str_malloc_mysqld; pcre_free= pcre_stack_free= my_str_free_mysqld; -#ifndef EMBEDDED_LIBRARY pcre_stack_guard= check_enough_stack_size_slow; /* See http://pcre.org/original/doc/html/pcrestack.html */ - my_pcre_frame_size= -pcre_exec(NULL, NULL, NULL, -999, -999, 0, NULL, 0) + 16; -#endif + my_pcre_frame_size= -pcre_exec(NULL, NULL, NULL, -999, -999, 0, NULL, 0); + // pcre can underestimate its stack usage. Use a safe value, as in the manual + set_if_bigger(my_pcre_frame_size, 500); + my_pcre_frame_size += 16; // Again, safety margin, see the manual } -- cgit v1.2.1 From 3ef5596505bd8d80fa80d1cf7514550434eb1d79 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 20 Jul 2017 15:52:06 +0200 Subject: MDEV-13175 Adding a new enum value at the end of a list triggers a table rebuild Backport of 7e29f2d64fb from 10.1. Create_field does not set BINARY_FLAG, so the check didn't work at all. Also, character sets were already compared, so this check would've been redundant (if it would've worked). --- sql/field.cc | 21 +++++++++++++-------- sql/field.h | 10 +--------- 2 files changed, 14 insertions(+), 17 deletions(-) (limited to 'sql') diff --git a/sql/field.cc b/sql/field.cc index 7d7fad2d84d..7a44bcadd3c 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -6403,9 +6403,6 @@ uint Field::is_equal(Create_field *new_field) uint Field_str::is_equal(Create_field *new_field) { - if (field_flags_are_binary() != new_field->field_flags_are_binary()) - return 0; - return ((new_field->sql_type == real_type()) && new_field->charset == field_charset && new_field->length == max_display_length()); @@ -7810,9 +7807,6 @@ uint Field_blob::max_packed_col_length(uint max_length) uint Field_blob::is_equal(Create_field *new_field) { - if (field_flags_are_binary() != new_field->field_flags_are_binary()) - return 0; - return ((new_field->sql_type == get_blob_type_from_length(max_data_length())) && new_field->charset == field_charset && new_field->pack_length == pack_length()); @@ -7933,6 +7927,18 @@ Field::geometry_type Field_geom::geometry_type_merge(geometry_type a, return Field::GEOM_GEOMETRY; } + +uint Field_geom::is_equal(Create_field *new_field) +{ + return new_field->sql_type == MYSQL_TYPE_GEOMETRY && + /* + - Allow ALTER..INPLACE to supertype (GEOMETRY), + e.g. POINT to GEOMETRY or POLYGON to GEOMETRY. + - Allow ALTER..INPLACE to the same geometry type: POINT -> POINT + */ + (new_field->geom_type == geom_type || + new_field->geom_type == GEOM_GEOMETRY); +} #endif /*HAVE_SPATIAL*/ /**************************************************************************** @@ -8336,8 +8342,7 @@ uint Field_enum::is_equal(Create_field *new_field) The fields are compatible if they have the same flags, type, charset and have the same underlying length. */ - if (new_field->field_flags_are_binary() != field_flags_are_binary() || - new_field->sql_type != real_type() || + if (new_field->sql_type != real_type() || new_field->charset != field_charset || new_field->pack_length != pack_length()) return IS_EQUAL_NO; diff --git a/sql/field.h b/sql/field.h index 2770b8be213..e7bd5532ae6 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1080,10 +1080,6 @@ protected: const uchar *unpack_int64(uchar* to, const uchar *from, const uchar *from_end) { return unpack_int(to, from, from_end, 8); } - bool field_flags_are_binary() - { - return (flags & (BINCMP_FLAG | BINARY_FLAG)) != 0; - } double pos_in_interval_val_real(Field *min, Field *max); double pos_in_interval_val_str(Field *min, Field *max, uint data_offset); }; @@ -2620,6 +2616,7 @@ public: enum_field_types type() const { return MYSQL_TYPE_GEOMETRY; } bool match_collation_to_optimize_range() const { return false; } void sql_type(String &str) const; + uint is_equal(Create_field *new_field); int store(const char *to, uint length, CHARSET_INFO *charset); int store(double nr); int store(longlong nr, bool unsigned_val); @@ -2967,11 +2964,6 @@ public: uint uint_geom_type, Virtual_column_info *vcol_info, engine_option_value *option_list, bool check_exists); - bool field_flags_are_binary() - { - return (flags & (BINCMP_FLAG | BINARY_FLAG)) != 0; - } - ha_storage_media field_storage_type() const { return (ha_storage_media) -- cgit v1.2.1 From 2804a3fac47a418bd4495463e25fc5c10b7f3e76 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 27 Jul 2017 12:42:21 +0200 Subject: memory leak: add a missing end_relay_log_info() --- sql/rpl_mi.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'sql') diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index 7cb093c9026..c810e030bf2 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -747,6 +747,7 @@ void free_key_master_info(Master_info *mi) /* We use 2 here instead of 1 just to make it easier when debugging */ mi->killed= 2; end_master_info(mi); + end_relay_log_info(&mi->rli); mi->unlock_slave_threads(); delete mi; -- cgit v1.2.1 From c784277590bad3a0d869ca51c03cbce897125924 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 27 Jul 2017 12:43:03 +0200 Subject: move the error message where it belongs --- sql/slave.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/slave.cc b/sql/slave.cc index b00bee5acee..45af5fcd337 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -385,6 +385,7 @@ int init_slave() { delete active_mi; active_mi= 0; + sql_print_error("Failed to allocate memory for the Master Info structure"); goto err; } @@ -446,7 +447,6 @@ end: DBUG_RETURN(error); err: - sql_print_error("Failed to allocate memory for the Master Info structure"); error= 1; goto end; } -- cgit v1.2.1 From 7134afa22e3ce91b8f729eaa01dae54e93947f71 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 27 Jul 2017 12:43:45 +0200 Subject: MYSQL_BIN_LOG::open/close must be under LOCK_log --- sql/rpl_rli.cc | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 9e20775a1aa..083e3649505 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -256,8 +256,8 @@ a file name for --relay-log-index option", opt_relaylog_index_name); if ((info_fd= mysql_file_open(key_file_relay_log_info, fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0) { - sql_print_error("Failed to create a new relay log info file (\ -file '%s', errno %d)", fname, my_errno); + sql_print_error("Failed to create a new relay log info file (" + "file '%s', errno %d)", fname, my_errno); msg= current_thd->get_stmt_da()->message(); goto err; } @@ -450,7 +450,9 @@ err: if (info_fd >= 0) mysql_file_close(info_fd, MYF(0)); rli->info_fd= -1; + mysql_mutex_lock(rli->relay_log.get_log_lock()); rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT); + mysql_mutex_unlock(rli->relay_log.get_log_lock()); mysql_mutex_unlock(&rli->data_lock); DBUG_RETURN(1); } @@ -1145,14 +1147,17 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset, "log index file:%s.", rli->relay_log.get_index_fname()); DBUG_RETURN(1); } + mysql_mutex_lock(rli->relay_log.get_log_lock()); if (rli->relay_log.open(ln, LOG_BIN, 0, SEQ_READ_APPEND, (rli->max_relay_log_size ? rli->max_relay_log_size : max_binlog_size), 1, TRUE)) { sql_print_error("Unable to purge relay log files. Failed to open relay " "log file:%s.", rli->relay_log.get_log_fname()); + mysql_mutex_unlock(rli->relay_log.get_log_lock()); DBUG_RETURN(1); } + mysql_mutex_unlock(rli->relay_log.get_log_lock()); } else DBUG_RETURN(0); @@ -1210,7 +1215,11 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset, } if (!rli->inited && rli->error_on_rli_init_info) + { + mysql_mutex_lock(rli->relay_log.get_log_lock()); rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT); + mysql_mutex_unlock(rli->relay_log.get_log_lock()); + } err: #ifndef DBUG_OFF char buf[22]; -- cgit v1.2.1 From af40426fcdacfa9e8e2868cf5d95ce671c1287a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Thu, 27 Jul 2017 16:20:26 +0300 Subject: Fix purge_relay_logs post merge slave_skip_counter must not be reset to 0 during purge_relay_logs. See MDEV-4937 as to when this change happened. --- sql/rpl_rli.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'sql') diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 083e3649505..eac4149cb06 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -1167,7 +1167,6 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset, DBUG_ASSERT(rli->slave_running == 0); DBUG_ASSERT(rli->mi->slave_running == 0); } - rli->slave_skip_counter=0; mysql_mutex_lock(&rli->data_lock); /* -- cgit v1.2.1 From 7f5a8f176ac59f0a15fb3723b5b2ab47b4fbe9e0 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Tue, 25 Jul 2017 10:57:25 +0400 Subject: MDEV-12915 ST_Centroid does not return the same result than MySQL. Calculation of the polygon's centroid fixed. --- sql/spatial.cc | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'sql') diff --git a/sql/spatial.cc b/sql/spatial.cc index bfe302f332e..b03a8b6da07 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -1150,8 +1150,8 @@ int Gis_polygon::centroid_xy(double *x, double *y) const uint32 n_points, org_n_points; double prev_x, prev_y; double cur_area= 0; - double cur_cx= 0; - double cur_cy= 0; + double cur_cx= 0, cur_cy= 0; + double sum_cx= 0, sum_cy= 0; if (no_data(data, 4)) return 1; @@ -1165,17 +1165,32 @@ int Gis_polygon::centroid_xy(double *x, double *y) const while (--n_points) // One point is already read { double tmp_x, tmp_y; + double loc_area; get_point(&tmp_x, &tmp_y, data); data+= POINT_DATA_SIZE; - cur_area+= (prev_x + tmp_x) * (prev_y - tmp_y); + loc_area= prev_x * tmp_y - tmp_x * prev_y; + cur_area+= loc_area; cur_cx+= tmp_x; cur_cy+= tmp_y; + sum_cx+= (prev_x + tmp_x) * loc_area; + sum_cy+= (prev_y + tmp_y) * loc_area; + prev_x= tmp_x; prev_y= tmp_y; } - cur_area= fabs(cur_area) / 2; - cur_cx= cur_cx / (org_n_points - 1); - cur_cy= cur_cy / (org_n_points - 1); + + if (fabs(cur_area) > 1e-10) + { + cur_cx= sum_cx / cur_area / 3.0; + cur_cy= sum_cy / cur_area / 3.0; + } + else + { + cur_cx= cur_cx / (org_n_points - 1); + cur_cy= cur_cy / (org_n_points - 1); + } + + cur_area= fabs(cur_area); if (!first_loop) { -- cgit v1.2.1 From 60343871a73220e2a44d1cebb36e4d109c52c11c Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 13 Nov 2015 17:53:16 +0100 Subject: MDEV-8453 Alter table not returning engine errors remove ~15 years old print_lock_error() function, use handler::print_error() instead Backport from 10.1 --- sql/handler.cc | 4 ++++ sql/lock.cc | 37 +++---------------------------------- 2 files changed, 7 insertions(+), 34 deletions(-) (limited to 'sql') diff --git a/sql/handler.cc b/sql/handler.cc index e51f17f1712..2696d69bfcf 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -3650,6 +3650,8 @@ void handler::print_error(int error, myf errflag) */ bool handler::get_error_message(int error, String* buf) { + DBUG_EXECUTE_IF("external_lock_failure", + buf->set_ascii(STRING_WITH_LEN("KABOOM!"));); return FALSE; } @@ -5944,6 +5946,8 @@ int handler::ha_external_lock(THD *thd, int lock_type) MYSQL_TABLE_LOCK_WAIT(m_psi, PSI_TABLE_EXTERNAL_LOCK, lock_type, { error= external_lock(thd, lock_type); }) + DBUG_EXECUTE_IF("external_lock_failure", error= HA_ERR_GENERIC;); + if (error == 0 || lock_type == F_UNLCK) { m_lock_type= lock_type; diff --git a/sql/lock.cc b/sql/lock.cc index 29afcc8f578..3354da2640b 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -92,7 +92,6 @@ extern HASH open_cache; static int lock_external(THD *thd, TABLE **table,uint count); static int unlock_external(THD *thd, TABLE **table,uint count); -static void print_lock_error(int error, TABLE *); /* Map the return value of thr_lock to an error from errmsg.txt */ static int thr_lock_errno_to_mysql[]= @@ -358,7 +357,7 @@ static int lock_external(THD *thd, TABLE **tables, uint count) if ((error=(*tables)->file->ha_external_lock(thd,lock_type))) { - print_lock_error(error, *tables); + (*tables)->file->print_error(error, MYF(0)); while (--i) { tables--; @@ -675,8 +674,8 @@ static int unlock_external(THD *thd, TABLE **table,uint count) (*table)->current_lock = F_UNLCK; if ((error=(*table)->file->ha_external_lock(thd, F_UNLCK))) { - error_code=error; - print_lock_error(error_code, *table); + error_code= error; + (*table)->file->print_error(error, MYF(0)); } } table++; @@ -898,36 +897,6 @@ bool lock_object_name(THD *thd, MDL_key::enum_mdl_namespace mdl_type, } -static void print_lock_error(int error, TABLE *table) -{ - int textno; - DBUG_ENTER("print_lock_error"); - - switch (error) { - case HA_ERR_LOCK_WAIT_TIMEOUT: - textno=ER_LOCK_WAIT_TIMEOUT; - break; - case HA_ERR_READ_ONLY_TRANSACTION: - textno=ER_READ_ONLY_TRANSACTION; - break; - case HA_ERR_LOCK_DEADLOCK: - textno=ER_LOCK_DEADLOCK; - break; - case HA_ERR_WRONG_COMMAND: - my_error(ER_ILLEGAL_HA, MYF(0), table->file->table_type(), - table->s->db.str, table->s->table_name.str); - DBUG_VOID_RETURN; - default: - textno=ER_CANT_LOCK; - break; - } - - my_error(textno, MYF(0), error); - - DBUG_VOID_RETURN; -} - - /**************************************************************************** Handling of global read locks -- cgit v1.2.1 From e6e23c0d4916e08a7ca6b1c68f5e8e63bb1cff83 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 19 Mar 2016 19:40:25 +0100 Subject: MDEV-9739 Assertion `m_status == DA_ERROR || m_status == DA_OK' failed in Diagnostics_area::message() ; connect.xml* tests fail in buildbot --- sql/sql_show.cc | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sql') diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 9a743388149..a3d834b0e42 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -5314,7 +5314,10 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, HA_STATUS_TIME | HA_STATUS_VARIABLE_EXTRA | HA_STATUS_AUTO)) != 0) + { + file->print_error(info_error, MYF(0)); goto err; + } enum row_type row_type = file->get_row_type(); switch (row_type) { -- cgit v1.2.1 From e35670f49804399a208671901fd6f755647c49e2 Mon Sep 17 00:00:00 2001 From: Monty Date: Thu, 3 Aug 2017 19:28:05 +0300 Subject: MDEV-12972 Random and Frequent Segfault Problem was a memory overflow in MRR Reviewed by Sergei Petruna. Testcase by Elena --- sql/multi_range_read.cc | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) (limited to 'sql') diff --git a/sql/multi_range_read.cc b/sql/multi_range_read.cc index e856400466d..1b79f815a0f 100644 --- a/sql/multi_range_read.cc +++ b/sql/multi_range_read.cc @@ -1231,28 +1231,18 @@ bool DsMrr_impl::setup_buffer_sharing(uint key_size_in_keybuf, ptrdiff_t bytes_for_keys= (full_buf_end - full_buf) - bytes_for_rowids; - if (bytes_for_keys < key_buff_elem_size + 1) - { - ptrdiff_t add= key_buff_elem_size + 1 - bytes_for_keys; - bytes_for_keys= key_buff_elem_size + 1; - bytes_for_rowids -= add; - } - - if (bytes_for_rowids < (ptrdiff_t)rowid_buf_elem_size + 1) - { - ptrdiff_t add= (ptrdiff_t)(rowid_buf_elem_size + 1 - bytes_for_rowids); - bytes_for_rowids= (ptrdiff_t)rowid_buf_elem_size + 1; - bytes_for_keys -= add; - } + if (bytes_for_keys < key_buff_elem_size + 1 || + bytes_for_rowids < (ptrdiff_t)rowid_buf_elem_size + 1) + return TRUE; /* Failed to provide minimum space for one of the buffers */ rowid_buffer_end= full_buf + bytes_for_rowids; rowid_buffer.set_buffer_space(full_buf, rowid_buffer_end); key_buffer= &backward_key_buf; key_buffer->set_buffer_space(rowid_buffer_end, full_buf_end); - if (!key_buffer->have_space_for(key_buff_elem_size) || - !rowid_buffer.have_space_for((size_t)rowid_buf_elem_size)) - return TRUE; /* Failed to provide minimum space for one of the buffers */ + /* The above code guarantees that the buffers are big enough */ + DBUG_ASSERT(key_buffer->have_space_for(key_buff_elem_size) && + rowid_buffer.have_space_for((size_t)rowid_buf_elem_size)); return FALSE; } -- cgit v1.2.1 From 74543698a76c02d1a81e17e5918ecbf6b795607b Mon Sep 17 00:00:00 2001 From: Monty Date: Sat, 5 Aug 2017 19:26:10 +0300 Subject: MDEV-13179 main.errors fails with wrong errno The problem was that the introduction of max-thread-mem-used can cause an allocation error very early, even before mysql_parse() is called. As mysql_parse() calls thd->reset_for_next_command(), which called clear_error(), the error number was lost. Fixed by adding an option to have unique messages for each KILL signal and change max-thread-mem-used to use this new feature. This removes a lot of problems with the original approach, where one could get errors signaled silenty almost any time. ixed by moving clear_error() from reset_for_next_command() to do_command(), before any memory allocation for the thread. Related changes: - reset_for_next_command() now have an optional parameter if we should call clear_error() or not. By default it's called, but not anymore from dispatch_command() which was the original problem. - Added optional paramater to clear_error() to force calling of reset_diagnostics_area(). Before clear_error() only called reset_diagnostics_area() if there was no error, so we normally called reset_diagnostics_area() twice. - This change removed several duplicated calls to clear_error() when starting a query. - Reset max_mem_used on COM_QUIT, to protect against kill during quit. - Use fatal_error() instead of setting is_fatal_error (cleanup) - Set fatal_error if max_thead_mem_used is signaled. (Same logic we use for other places where we are out of resources) --- sql/debug_sync.cc | 2 +- sql/log_event.cc | 21 +++++-------- sql/mysqld.cc | 20 +++++++----- sql/mysqld.h | 2 +- sql/rpl_parallel.cc | 8 ++--- sql/sp_rcontext.cc | 3 +- sql/sql_base.cc | 4 +-- sql/sql_cache.cc | 5 ++- sql/sql_class.cc | 31 ++++++++++++------ sql/sql_class.h | 85 ++++++++++++++++++++++++++++++++++++++++++-------- sql/sql_connect.cc | 2 +- sql/sql_insert.cc | 14 ++++----- sql/sql_load.cc | 2 +- sql/sql_parse.cc | 44 +++++++++++++++----------- sql/sql_select.cc | 2 +- sql/sql_table.cc | 2 +- sql/sql_update.cc | 2 +- sql/threadpool_unix.cc | 2 +- sql/threadpool_win.cc | 2 +- sql/wsrep_mysqld.cc | 4 +-- sql/wsrep_thd.cc | 2 +- 21 files changed, 165 insertions(+), 94 deletions(-) (limited to 'sql') diff --git a/sql/debug_sync.cc b/sql/debug_sync.cc index 8b3412eb732..f6291ca7acc 100644 --- a/sql/debug_sync.cc +++ b/sql/debug_sync.cc @@ -1502,7 +1502,7 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action) { if (!--action->hit_limit) { - thd->killed= KILL_QUERY; + thd->set_killed(KILL_QUERY); my_error(ER_DEBUG_SYNC_HIT_LIMIT, MYF(0)); } DBUG_PRINT("debug_sync_exec", ("hit_limit: %lu at: '%s'", diff --git a/sql/log_event.cc b/sql/log_event.cc index 4265a23df2b..92885344cd6 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -371,12 +371,6 @@ static void pretty_print_str(IO_CACHE* cache, const char* str, int len) #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) -static void clear_all_errors(THD *thd, Relay_log_info *rli) -{ - thd->is_slave_error = 0; - thd->clear_error(); -} - inline int idempotent_error_code(int err_code) { int ret= 0; @@ -4255,7 +4249,7 @@ int Query_log_event::do_apply_event(rpl_group_info *rgi, DBUG_PRINT("info", ("log_pos: %lu", (ulong) log_pos)); - clear_all_errors(thd, const_cast(rli)); + thd->clear_error(1); current_stmt_is_commit= is_commit(); DBUG_ASSERT(!current_stmt_is_commit || !rgi->tables_to_lock); @@ -4475,7 +4469,7 @@ int Query_log_event::do_apply_event(rpl_group_info *rgi, to check/fix it. */ if (mysql_test_parse_for_slave(thd, thd->query(), thd->query_length())) - clear_all_errors(thd, const_cast(rli)); /* Can ignore query */ + thd->clear_error(1); else { rli->report(ERROR_LEVEL, expected_error, rgi->gtid_info(), @@ -4556,7 +4550,7 @@ compare_errors: ignored_error_code(actual_error)) { DBUG_PRINT("info",("error ignored")); - clear_all_errors(thd, const_cast(rli)); + thd->clear_error(1); if (actual_error == ER_QUERY_INTERRUPTED || actual_error == ER_CONNECTION_KILLED) thd->reset_killed(); @@ -6025,8 +6019,7 @@ int Load_log_event::do_apply_event(NET* net, rpl_group_info *rgi, new_db.str= (char *) rpl_filter->get_rewrite_db(db, &new_db.length); thd->set_db(new_db.str, new_db.length); DBUG_ASSERT(thd->query() == 0); - thd->is_slave_error= 0; - clear_all_errors(thd, const_cast(rli)); + thd->clear_error(1); /* see Query_log_event::do_apply_event() and BUG#13360 */ DBUG_ASSERT(!rgi->m_table_map.count()); @@ -6036,7 +6029,7 @@ int Load_log_event::do_apply_event(NET* net, rpl_group_info *rgi, */ lex_start(thd); thd->lex->local_file= local_fname; - thd->reset_for_next_command(); + thd->reset_for_next_command(0); // Errors are cleared above /* We test replicate_*_db rules. Note that we have already prepared @@ -10091,7 +10084,7 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) slave_rows_error_report(WARNING_LEVEL, error, rgi, thd, table, get_type_str(), RPL_LOG_NAME, (ulong) log_pos); - clear_all_errors(thd, const_cast(rli)); + thd->clear_error(1); error= 0; if (idempotent_error == 0) break; @@ -10143,7 +10136,7 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) slave_rows_error_report(WARNING_LEVEL, error, rgi, thd, table, get_type_str(), RPL_LOG_NAME, (ulong) log_pos); - clear_all_errors(thd, const_cast(rli)); + thd->clear_error(1); error= 0; } } // if (table) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 17172207613..e363c6de3f1 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -878,7 +878,7 @@ PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list, key_LOCK_prepared_stmt_count, key_LOCK_rpl_status, key_LOCK_server_started, key_LOCK_status, key_LOCK_show_status, - key_LOCK_system_variables_hash, key_LOCK_thd_data, + key_LOCK_system_variables_hash, key_LOCK_thd_data, key_LOCK_thd_kill, key_LOCK_user_conn, key_LOCK_uuid_short_generator, key_LOG_LOCK_log, key_master_info_data_lock, key_master_info_run_lock, key_master_info_sleep_lock, key_master_info_start_stop_lock, @@ -949,6 +949,7 @@ static PSI_mutex_info all_server_mutexes[]= { &key_LOCK_wait_commit, "wait_for_commit::LOCK_wait_commit", 0}, { &key_LOCK_gtid_waiting, "gtid_waiting::LOCK_gtid_waiting", 0}, { &key_LOCK_thd_data, "THD::LOCK_thd_data", 0}, + { &key_LOCK_thd_kill, "THD::LOCK_thd_kill", 0}, { &key_LOCK_user_conn, "LOCK_user_conn", PSI_FLAG_GLOBAL}, { &key_LOCK_uuid_short_generator, "LOCK_uuid_short_generator", PSI_FLAG_GLOBAL}, { &key_LOG_LOCK_log, "LOG::LOCK_log", 0}, @@ -1650,7 +1651,7 @@ static void close_connections(void) if (WSREP(tmp) && (tmp->wsrep_exec_mode==REPL_RECV || tmp->wsrep_applier)) continue; #endif - tmp->killed= KILL_SERVER_HARD; + tmp->set_killed(KILL_SERVER_HARD); MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (tmp)); mysql_mutex_lock(&tmp->LOCK_thd_data); if (tmp->mysys_var) @@ -1738,7 +1739,7 @@ static void close_connections(void) if (WSREP(tmp) && tmp->wsrep_exec_mode==REPL_RECV) { sql_print_information("closing wsrep system thread"); - tmp->killed= KILL_CONNECTION; + tmp->set_killed(KILL_CONNECTION); MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (tmp)); if (tmp->mysys_var) { @@ -3943,11 +3944,16 @@ static void my_malloc_size_cb_func(long long size, my_bool is_thread_specific) thd->status_var.local_memory_used > (int64)thd->variables.max_mem_used && !thd->killed && !thd->get_stmt_da()->is_set()) { - char buf[1024]; - thd->killed= KILL_QUERY; + /* Ensure we don't get called here again */ + char buf[50], *buf2; + thd->set_killed(KILL_QUERY); my_snprintf(buf, sizeof(buf), "--max-thread-mem-used=%llu", thd->variables.max_mem_used); - my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), buf); + if ((buf2= (char*) thd->alloc(256))) + { + my_snprintf(buf2, 256, ER_THD(thd, ER_OPTION_PREVENTS_STATEMENT), buf); + thd->set_killed(KILL_QUERY, ER_OPTION_PREVENTS_STATEMENT, buf2); + } } DBUG_ASSERT((longlong) thd->status_var.local_memory_used >= 0); } @@ -6318,7 +6324,7 @@ void create_thread_to_handle_connection(THD *thd) DBUG_PRINT("error", ("Can't create thread to handle request (error %d)", error)); - thd->killed= KILL_CONNECTION; // Safety + thd->set_killed(KILL_CONNECTION); // Safety mysql_mutex_unlock(&LOCK_thread_count); mysql_mutex_lock(&LOCK_connection_count); diff --git a/sql/mysqld.h b/sql/mysqld.h index 419dbac1613..0725d862553 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -290,7 +290,7 @@ extern PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list, key_LOCK_prepared_stmt_count, key_LOCK_rpl_status, key_LOCK_server_started, key_LOCK_status, key_LOCK_show_status, - key_LOCK_thd_data, + key_LOCK_thd_data, key_LOCK_thd_kill, key_LOCK_user_conn, key_LOG_LOCK_log, key_master_info_data_lock, key_master_info_run_lock, key_master_info_sleep_lock, key_master_info_start_stop_lock, diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index f05239ce1ba..35cddee6d4d 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -714,9 +714,7 @@ do_retry: DBUG_EXECUTE_IF("inject_mdev8031", { /* Simulate that we get deadlock killed at this exact point. */ rgi->killed_for_retry= rpl_group_info::RETRY_KILL_KILLED; - mysql_mutex_lock(&thd->LOCK_thd_data); - thd->killed= KILL_CONNECTION; - mysql_mutex_unlock(&thd->LOCK_thd_data); + thd->set_killed(KILL_CONNECTION); }); rgi->cleanup_context(thd, 1); wait_for_pending_deadlock_kill(thd, rgi); @@ -862,9 +860,7 @@ do_retry: /* Simulate that we get deadlock killed during open_binlog(). */ thd->reset_for_next_command(); rgi->killed_for_retry= rpl_group_info::RETRY_KILL_KILLED; - mysql_mutex_lock(&thd->LOCK_thd_data); - thd->killed= KILL_CONNECTION; - mysql_mutex_unlock(&thd->LOCK_thd_data); + thd->set_killed(KILL_CONNECTION); thd->send_kill_message(); fd= (File)-1; err= 1; diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index b38f4a3ddad..4d74d2721f1 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -331,8 +331,7 @@ bool sp_rcontext::handle_sql_condition(THD *thd, /* Reset error state. */ thd->clear_error(); - thd->killed= NOT_KILLED; // Some errors set thd->killed - // (e.g. "bad data"). + thd->reset_killed(); // Some errors set thd->killed, (e.g. "bad data"). /* Add a frame to handler-call-stack. */ Sql_condition_info *cond_info= diff --git a/sql/sql_base.cc b/sql/sql_base.cc index ae10c0b771d..1aaeb2a5584 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -400,7 +400,7 @@ void kill_delayed_threads_for_table(TDC_element *element) if ((in_use->system_thread & SYSTEM_THREAD_DELAYED_INSERT) && ! in_use->killed) { - in_use->killed= KILL_SYSTEM_THREAD; + in_use->set_killed(KILL_SYSTEM_THREAD); mysql_mutex_lock(&in_use->mysys_var->mutex); if (in_use->mysys_var->current_cond) { @@ -9136,7 +9136,7 @@ bool mysql_notify_thread_having_shared_lock(THD *thd, THD *in_use, if ((in_use->system_thread & SYSTEM_THREAD_DELAYED_INSERT) && !in_use->killed) { - in_use->killed= KILL_SYSTEM_THREAD; + in_use->set_killed(KILL_SYSTEM_THREAD); mysql_mutex_lock(&in_use->mysys_var->mutex); if (in_use->mysys_var->current_cond) { diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index c69303c5273..66ac2449519 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -2160,8 +2160,7 @@ lookup: response, we can't handle it anyway. */ (void) trans_commit_stmt(thd); - if (!thd->get_stmt_da()->is_set()) - thd->get_stmt_da()->disable_status(); + thd->get_stmt_da()->disable_status(); BLOCK_UNLOCK_RD(query_block); MYSQL_QUERY_CACHE_HIT(thd->query(), (ulong) thd->limit_found_rows); @@ -4615,7 +4614,7 @@ void Query_cache::wreck(uint line, const char *message) DBUG_PRINT("warning", ("%5d QUERY CACHE WRECK => DISABLED",line)); DBUG_PRINT("warning", ("==================================")); if (thd) - thd->killed= KILL_CONNECTION; + thd->set_killed(KILL_CONNECTION); cache_dump(); /* check_integrity(0); */ /* Can't call it here because of locks */ bins_dump(); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 78b8b3f05eb..63663cdd037 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -333,7 +333,7 @@ void thd_set_psi(THD *thd, PSI_thread *psi) */ void thd_set_killed(THD *thd) { - thd->killed= KILL_CONNECTION; + thd->set_killed(KILL_CONNECTION); } /** @@ -935,6 +935,7 @@ THD::THD(bool is_wsrep_applier) query_start_used= query_start_sec_part_used= 0; count_cuted_fields= CHECK_FIELD_IGNORE; killed= NOT_KILLED; + killed_err= 0; col_access=0; is_slave_error= thread_specific_used= FALSE; my_hash_clear(&handler_tables_hash); @@ -992,6 +993,7 @@ THD::THD(bool is_wsrep_applier) #endif mysql_mutex_init(key_LOCK_thd_data, &LOCK_thd_data, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_wakeup_ready, &LOCK_wakeup_ready, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_thd_kill, &LOCK_thd_kill, MY_MUTEX_INIT_FAST); mysql_cond_init(key_COND_wakeup_ready, &COND_wakeup_ready, 0); /* LOCK_thread_count goes before LOCK_thd_data - the former is called around @@ -1256,7 +1258,7 @@ Sql_condition* THD::raise_condition(uint sql_errno, push_warning and strict SQL_MODE case. */ level= Sql_condition::WARN_LEVEL_ERROR; - killed= KILL_BAD_DATA; + set_killed(KILL_BAD_DATA); } switch (level) @@ -1564,7 +1566,7 @@ void THD::cleanup(void) DBUG_ENTER("THD::cleanup"); DBUG_ASSERT(cleanup_done == 0); - killed= KILL_CONNECTION; + set_killed(KILL_CONNECTION); #ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE if (transaction.xid_state.xa_state == XA_PREPARED) { @@ -1667,6 +1669,7 @@ THD::~THD() mysql_cond_destroy(&COND_wakeup_ready); mysql_mutex_destroy(&LOCK_wakeup_ready); mysql_mutex_destroy(&LOCK_thd_data); + mysql_mutex_destroy(&LOCK_thd_kill); #ifndef DBUG_OFF dbug_sentry= THD_SENTRY_GONE; #endif @@ -1839,7 +1842,8 @@ void THD::awake(killed_state state_to_set) state_to_set= killed; /* Set the 'killed' flag of 'this', which is the target THD object. */ - killed= state_to_set; + mysql_mutex_lock(&LOCK_thd_kill); + set_killed_no_mutex(state_to_set); if (state_to_set >= KILL_CONNECTION || state_to_set == NOT_KILLED) { @@ -1925,6 +1929,7 @@ void THD::awake(killed_state state_to_set) } mysql_mutex_unlock(&mysys_var->mutex); } + mysql_mutex_unlock(&LOCK_thd_kill); DBUG_VOID_RETURN; } @@ -1942,7 +1947,7 @@ void THD::disconnect() mysql_mutex_lock(&LOCK_thd_data); - killed= KILL_CONNECTION; + set_killed(KILL_CONNECTION); #ifdef SIGNAL_WITH_VIO_CLOSE /* @@ -1978,7 +1983,7 @@ bool THD::notify_shared_lock(MDL_context_owner *ctx_in_use, DBUG_PRINT("info", ("kill delayed thread")); mysql_mutex_lock(&in_use->LOCK_thd_data); if (in_use->killed < KILL_CONNECTION) - in_use->killed= KILL_CONNECTION; + in_use->set_killed(KILL_CONNECTION); if (in_use->mysys_var) { mysql_mutex_lock(&in_use->mysys_var->mutex); @@ -2031,13 +2036,21 @@ bool THD::notify_shared_lock(MDL_context_owner *ctx_in_use, /* Get error number for killed state Note that the error message can't have any parameters. + If one needs parameters, one should use THD::killed_err_msg See thd::kill_message() */ -int killed_errno(killed_state killed) +int THD::killed_errno() { DBUG_ENTER("killed_errno"); - DBUG_PRINT("enter", ("killed: %d", killed)); + DBUG_PRINT("enter", ("killed: %d killed_errno: %d", + killed, killed_err ? killed_err->no: 0)); + + /* Ensure that killed_err is not set if we are not killed */ + DBUG_ASSERT(!killed_err || killed != NOT_KILLED); + + if (killed_err) + DBUG_RETURN(killed_err->no); switch (killed) { case NOT_KILLED: @@ -2478,7 +2491,7 @@ CHANGED_TABLE_LIST* THD::changed_table_dup(const char *key, long key_length) { my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_FATALERROR), ALIGN_SIZE(sizeof(TABLE_LIST)) + key_length + 1); - killed= KILL_CONNECTION; + set_killed(KILL_CONNECTION); return 0; } diff --git a/sql/sql_class.h b/sql/sql_class.h index 342902363c6..44163333425 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -482,7 +482,6 @@ enum killed_state KILL_SERVER_HARD= 15 }; -extern int killed_errno(killed_state killed); #define killed_mask_hard(killed) ((killed_state) ((killed) & ~KILL_HARD_BIT)) enum killed_type @@ -1924,7 +1923,7 @@ public: rpl_sql_thread_info *rpl_sql_info; } system_thread_info; - void reset_for_next_command(); + void reset_for_next_command(bool do_clear_errors= 1); /* Constant for THD::where initialization in the beginning of every query. @@ -1980,6 +1979,8 @@ public: Is locked when THD is deleted. */ mysql_mutex_t LOCK_thd_data; + /* Protect kill information */ + mysql_mutex_t LOCK_thd_kill; /* all prepared statements and cursors of this connection */ Statement_map stmt_map; @@ -2615,7 +2616,7 @@ public: void check_limit_rows_examined() { if (++accessed_rows_and_keys > lex->limit_rows_examined_cnt) - killed= ABORT_QUERY; + set_killed(ABORT_QUERY); } USER_CONN *user_connect; @@ -2716,6 +2717,16 @@ public: */ killed_state volatile killed; + /* + The following is used if one wants to have a specific error number and + text for the kill + */ + struct err_info + { + int no; + const char msg[256]; + } *killed_err; + /* See also thd_killed() */ inline bool check_killed() { @@ -3280,18 +3291,18 @@ public: @todo: To silence an error, one should use Internal_error_handler mechanism. Issuing an error that can be possibly later "cleared" is not compatible with other installed error handlers and audit plugins. - In future this function will be removed. */ - inline void clear_error() + inline void clear_error(bool clear_diagnostics= 0) { DBUG_ENTER("clear_error"); - if (get_stmt_da()->is_error()) + if (get_stmt_da()->is_error() || clear_diagnostics) get_stmt_da()->reset_diagnostics_area(); is_slave_error= 0; if (killed == KILL_BAD_DATA) - killed= NOT_KILLED; // KILL_BAD_DATA can be reset w/o a mutex + reset_killed(); DBUG_VOID_RETURN; } + #ifndef EMBEDDED_LIBRARY inline bool vio_ok() const { return net.vio != 0; } /** Return FALSE if connection to client is broken. */ @@ -3401,10 +3412,54 @@ public: state after execution of a non-prepared SQL statement. */ void end_statement(); - inline int killed_errno() const + + /* + Mark thread to be killed, with optional error number and string. + string is not released, so it has to be allocted on thd mem_root + or be a global string + + Ensure that we don't replace a kill with a lesser one. For example + if user has done 'kill_connection' we shouldn't replace it with + KILL_QUERY. + */ + inline void set_killed(killed_state killed_arg, + int killed_errno_arg= 0, + const char *killed_err_msg_arg= 0) { - return ::killed_errno(killed); + mysql_mutex_lock(&LOCK_thd_kill); + set_killed_no_mutex(killed_arg, killed_errno_arg, killed_err_msg_arg); + mysql_mutex_unlock(&LOCK_thd_kill); } + /* + This is only used by THD::awake where we need to keep the lock mutex + locked over some time. + It's ok to have this inline, as in most cases killed_errno_arg will + be a constant 0 and most of the function will disappear. + */ + inline void set_killed_no_mutex(killed_state killed_arg, + int killed_errno_arg= 0, + const char *killed_err_msg_arg= 0) + { + if (killed <= killed_arg) + { + killed= killed_arg; + if (killed_errno_arg) + { + /* + If alloc fails, we only remember the killed flag. + The worst things that can happen is that we get + a suboptimal error message. + */ + if ((killed_err= (err_info*) alloc(sizeof(*killed_err)))) + { + killed_err->no= killed_errno_arg; + ::strmake((char*) killed_err->msg, killed_err_msg_arg, + sizeof(killed_err->msg)-1); + } + } + } + } + int killed_errno(); inline void reset_killed() { /* @@ -3413,9 +3468,10 @@ public: */ if (killed != NOT_KILLED) { - mysql_mutex_lock(&LOCK_thd_data); + mysql_mutex_lock(&LOCK_thd_kill); killed= NOT_KILLED; - mysql_mutex_unlock(&LOCK_thd_data); + killed_err= 0; + mysql_mutex_unlock(&LOCK_thd_kill); } } inline void reset_kill_query() @@ -3426,11 +3482,14 @@ public: mysys_var->abort= 0; } } - inline void send_kill_message() const + inline void send_kill_message() { + mysql_mutex_lock(&LOCK_thd_kill); int err= killed_errno(); if (err) - my_message(err, ER_THD(this, err), MYF(0)); + my_message(err, killed_err ? killed_err->msg : ER_THD(this, err), + MYF(0)); + mysql_mutex_unlock(&LOCK_thd_kill); } /* return TRUE if we will abort query if we make a warning now */ inline bool really_abort_on_warning() diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 7befde1c1f3..ac5b6ab29a2 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -1196,7 +1196,7 @@ void prepare_new_connection_state(THD* thd) if (thd->is_error()) { Host_errors errors; - thd->killed= KILL_CONNECTION; + thd->set_killed(KILL_CONNECTION); thd->print_aborted_warning(0, "init_connect command failed"); sql_print_warning("%s", thd->get_stmt_da()->message()); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 092b2154c61..721fff389e0 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2681,7 +2681,7 @@ void kill_delayed_threads(void) { mysql_mutex_lock(&di->thd.LOCK_thd_data); if (di->thd.killed < KILL_CONNECTION) - di->thd.killed= KILL_CONNECTION; + di->thd.set_killed(KILL_CONNECTION); if (di->thd.mysys_var) { mysql_mutex_lock(&di->thd.mysys_var->mutex); @@ -2827,7 +2827,7 @@ pthread_handler_t handle_delayed_insert(void *arg) thd->set_current_time(); threads.append(thd); if (abort_loop) - thd->killed= KILL_CONNECTION; + thd->set_killed(KILL_CONNECTION); else thd->reset_killed(); mysql_mutex_unlock(&LOCK_thread_count); @@ -2972,7 +2972,7 @@ pthread_handler_t handle_delayed_insert(void *arg) } #endif if (error == ETIMEDOUT || error == ETIME) - thd->killed= KILL_CONNECTION; + thd->set_killed(KILL_CONNECTION); } /* We can't lock di->mutex and mysys_var->mutex at the same time */ mysql_mutex_unlock(&di->mutex); @@ -3001,7 +3001,7 @@ pthread_handler_t handle_delayed_insert(void *arg) if (! (thd->lock= mysql_lock_tables(thd, &di->table, 1, 0))) { /* Fatal error */ - thd->killed= KILL_CONNECTION; + thd->set_killed(KILL_CONNECTION); } mysql_cond_broadcast(&di->cond_client); } @@ -3010,7 +3010,7 @@ pthread_handler_t handle_delayed_insert(void *arg) if (di->handle_inserts()) { /* Some fatal error */ - thd->killed= KILL_CONNECTION; + thd->set_killed(KILL_CONNECTION); } } di->status=0; @@ -3054,7 +3054,7 @@ pthread_handler_t handle_delayed_insert(void *arg) this. */ mysql_mutex_lock(&thd->LOCK_thd_data); - thd->killed= KILL_CONNECTION_HARD; // If error + thd->set_killed(KILL_CONNECTION_HARD); // If error thd->mdl_context.set_needs_thr_lock_abort(0); mysql_mutex_unlock(&thd->LOCK_thd_data); @@ -3143,7 +3143,7 @@ bool Delayed_insert::handle_inserts(void) max_rows= delayed_insert_limit; if (thd.killed || table->s->tdc->flushed) { - thd.killed= KILL_SYSTEM_THREAD; + thd.set_killed(KILL_SYSTEM_THREAD); max_rows= ULONG_MAX; // Do as much as possible } diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 0168f46f8ee..25bc29de401 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -613,7 +613,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, DBUG_EXECUTE_IF("simulate_kill_bug27571", { error=1; - thd->killed= KILL_QUERY; + thd->set_killed(KILL_QUERY); };); #ifndef EMBEDDED_LIBRARY diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c4b32933b8a..a1da14d5c53 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -669,6 +669,7 @@ void execute_init_command(THD *thd, LEX_STRING *init_command, */ save_vio= thd->net.vio; thd->net.vio= 0; + thd->clear_error(1); dispatch_command(COM_QUERY, thd, buf, len); thd->client_capabilities= save_client_capabilities; thd->net.vio= save_vio; @@ -800,6 +801,7 @@ static void handle_bootstrap_impl(THD *thd) if (bootstrap_error) break; + thd->reset_kill_query(); /* Ensure that killed_errmsg is released */ free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); free_root(&thd->transaction.mem_root,MYF(MY_KEEP_PREALLOC)); thd->lex->restore_set_statement_var(); @@ -954,13 +956,8 @@ bool do_command(THD *thd) if(!thd->skip_wait_timeout) my_net_set_read_timeout(net, thd->variables.net_wait_timeout); - - /* - XXX: this code is here only to clear possible errors of init_connect. - Consider moving to init_connect() instead. - */ - thd->clear_error(); // Clear error message - thd->get_stmt_da()->reset_diagnostics_area(); + /* Errors and diagnostics are cleared once here before query */ + thd->clear_error(1); net_new_transaction(net); @@ -1123,6 +1120,7 @@ bool do_command(THD *thd) WSREP_WARN("For retry temporally setting character set to : %s", my_charset_latin1.csname); } + thd->clear_error(); return_value= dispatch_command(command, thd, thd->wsrep_retry_query, thd->wsrep_retry_query_len); thd->variables.character_set_client = current_charset; @@ -1272,7 +1270,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); WSREP_DEBUG("Deadlock error for: %s", thd->query()); mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - thd->killed = NOT_KILLED; + thd->reset_killed(); thd->mysys_var->abort = 0; thd->wsrep_conflict_state = NO_CONFLICT; thd->wsrep_retry_counter = 0; @@ -1625,7 +1623,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; } packet= arg_end + 1; - thd->reset_for_next_command(); + thd->reset_for_next_command(0); // Don't clear errors lex_start(thd); /* Must be before we init the table list. */ if (lower_case_table_names) @@ -1694,7 +1692,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } #endif case COM_QUIT: - /* We don't calculate statistics for this command */ + /* Note: We don't calculate statistics for this command */ + + /* Ensure that quit works even if max_mem_used is set */ + thd->variables.max_mem_used= LONGLONG_MAX; general_log_print(thd, command, NullS); net->error=0; // Don't give 'abort' message thd->get_stmt_da()->disable_status(); // Don't send anything back @@ -1974,6 +1975,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, dec_thread_running(); thd->packet.shrink(thd->variables.net_buffer_length); // Reclaim some memory + thd->reset_kill_query(); /* Ensure that killed_errmsg is released */ free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); #if defined(ENABLED_PROFILING) @@ -5047,7 +5049,7 @@ end_with_restore_list: /* Disconnect the current client connection. */ if (tx_release) { - thd->killed= KILL_CONNECTION; + thd->set_killed(KILL_CONNECTION); thd->print_aborted_warning(3, "RELEASE"); } #ifdef WITH_WSREP @@ -5093,7 +5095,7 @@ end_with_restore_list: } /* Disconnect the current client connection. */ if (tx_release) - thd->killed= KILL_CONNECTION; + thd->set_killed(KILL_CONNECTION); #ifdef WITH_WSREP if (WSREP(thd) && thd->wsrep_conflict_state != NO_CONFLICT) { @@ -6879,6 +6881,8 @@ bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize) Reset the part of THD responsible for the state of command processing. + @param do_clear_error Set if we should clear errors + This needs to be called before execution of every statement (prepared or conventional). It is not called by substatements of routines. @@ -6886,12 +6890,16 @@ bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize) @todo Call it after we use THD for queries, not before. */ -void THD::reset_for_next_command() +void THD::reset_for_next_command(bool do_clear_error) { THD *thd= this; DBUG_ENTER("THD::reset_for_next_command"); DBUG_ASSERT(!thd->spcont); /* not for substatements of routines */ DBUG_ASSERT(! thd->in_sub_stmt); + + if (do_clear_error) + clear_error(1); + thd->free_list= 0; thd->select_number= 1; /* @@ -6947,8 +6955,6 @@ void THD::reset_for_next_command() reset_dynamic(&thd->user_var_events); thd->user_var_events_alloc= thd->mem_root; } - thd->clear_error(); - thd->get_stmt_da()->reset_diagnostics_area(); thd->get_stmt_da()->reset_for_next_command(); thd->rand_used= 0; thd->m_sent_row_count= thd->m_examined_row_count= 0; @@ -7180,7 +7186,7 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, thd->wsrep_conflict_state == CERT_FAILURE) { thd->reset_for_next_command(); - thd->killed= NOT_KILLED; + thd->reset_killed(); if (is_autocommit && thd->lex->sql_command != SQLCOM_SELECT && (thd->wsrep_retry_counter < thd->variables.wsrep_retry_autocommit)) @@ -7208,7 +7214,7 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, thd->thread_id, is_autocommit, thd->wsrep_retry_counter, thd->variables.wsrep_retry_autocommit, thd->query()); my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); - thd->killed= NOT_KILLED; + thd->reset_killed(); thd->wsrep_conflict_state= NO_CONFLICT; if (thd->wsrep_conflict_state != REPLAYING) thd->wsrep_retry_counter= 0; // reset @@ -8282,10 +8288,10 @@ void sql_kill(THD *thd, longlong id, killed_state state, killed_type type) uint error; if (!(error= kill_one_thread(thd, id, state, type))) { - if ((!thd->killed)) + if (!thd->killed) my_ok(thd); else - my_error(killed_errno(thd->killed), MYF(0), id); + thd->send_kill_message(); } else my_error(error, MYF(0), id); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 37d7c801b43..f9da12aac29 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3592,7 +3592,7 @@ make_join_statistics(JOIN *join, List &tables_list, #endif DBUG_EXECUTE_IF("bug11747970_raise_error", - { join->thd->killed= KILL_QUERY_HARD; }); + { join->thd->set_killed(KILL_QUERY_HARD); }); if (error) { table->file->print_error(error, MYF(0)); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index ace8ff1a7a9..29c382f57d6 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4783,7 +4783,7 @@ int create_table_impl(THD *thd, thd->variables.option_bits|= OPTION_KEEP_LOG; thd->log_current_statement= 1; create_info->table_was_deleted= 1; - DBUG_EXECUTE_IF("send_kill_after_delete", thd->killed= KILL_QUERY; ); + DBUG_EXECUTE_IF("send_kill_after_delete", thd->set_killed(KILL_QUERY); ); /* Restart statement transactions for the case of CREATE ... SELECT. diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 5ccc2384b84..a87261aa34b 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -940,7 +940,7 @@ int mysql_update(THD *thd, // simulated killing after the loop must be ineffective for binlogging DBUG_EXECUTE_IF("simulate_kill_bug27571", { - thd->killed= KILL_QUERY; + thd->set_killed(KILL_QUERY); };); error= (killed_status == NOT_KILLED)? error : 1; diff --git a/sql/threadpool_unix.cc b/sql/threadpool_unix.cc index 5d46b8790c5..f1133b22cf5 100644 --- a/sql/threadpool_unix.cc +++ b/sql/threadpool_unix.cc @@ -463,7 +463,7 @@ static void timeout_check(pool_timer_t *timer) { /* Wait timeout exceeded, kill connection. */ mysql_mutex_lock(&thd->LOCK_thd_data); - thd->killed = KILL_CONNECTION; + thd->set_killed(KILL_CONNECTION); post_kill_notification(thd); mysql_mutex_unlock(&thd->LOCK_thd_data); } diff --git a/sql/threadpool_win.cc b/sql/threadpool_win.cc index eda759a24e9..cb44687f154 100644 --- a/sql/threadpool_win.cc +++ b/sql/threadpool_win.cc @@ -613,7 +613,7 @@ static VOID CALLBACK timer_callback(PTP_CALLBACK_INSTANCE instance, if (timeout <= now()) { - con->thd->killed = KILL_CONNECTION; + con->thd->set_killed(KILL_CONNECTION); if(con->thd->net.vio) vio_shutdown(con->thd->net.vio, SD_BOTH); } diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 9eaaa620200..617aebae82e 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1965,7 +1965,7 @@ static bool have_client_connections() static void wsrep_close_thread(THD *thd) { - thd->killed= KILL_CONNECTION; + thd->set_killed(KILL_CONNECTION); MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (thd)); if (thd->mysys_var) { @@ -2045,7 +2045,7 @@ void wsrep_close_client_connections(my_bool wait_to_end) if (is_replaying_connection(tmp)) { - tmp->killed= KILL_CONNECTION; + tmp->set_killed(KILL_CONNECTION); continue; } diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index 53632f56167..7b73273b8a9 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -232,7 +232,7 @@ void wsrep_replay_transaction(THD *thd) mysql_mutex_unlock(&thd->LOCK_wsrep_thd); thd->reset_for_next_command(); - thd->killed= NOT_KILLED; + thd->reset_killed(); close_thread_tables(thd); if (thd->locked_tables_mode && thd->lock) { -- cgit v1.2.1 From 19f2b3d02f1ae8028bcc388e9fd161737056f1fe Mon Sep 17 00:00:00 2001 From: Monty Date: Sat, 5 Aug 2017 19:26:31 +0300 Subject: Fixed compiler warnings --- sql/item_func.cc | 2 +- sql/slave.cc | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/item_func.cc b/sql/item_func.cc index b544f78fc12..5539ba7fc48 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3959,7 +3959,7 @@ longlong Item_master_gtid_wait::val_int() { DBUG_ASSERT(fixed == 1); longlong result= 0; - String *gtid_pos = args[0]->val_str(&value); + String *gtid_pos __attribute__((unused)) = args[0]->val_str(&value); if (args[0]->null_value) { diff --git a/sql/slave.cc b/sql/slave.cc index d87ac0e6ba3..1e093f97fa8 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3611,7 +3611,9 @@ int apply_event_and_update_pos_for_parallel(Log_event* ev, THD* thd, rpl_group_info *rgi) { +#ifndef DBUG_OFF Relay_log_info* rli= rgi->rli; +#endif mysql_mutex_assert_not_owner(&rli->data_lock); int reason= apply_event_and_update_pos_setup(ev, thd, rgi); /* -- cgit v1.2.1 From 5099d6de61fd03b8225dfba9e4becb13b5a74c67 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 8 Aug 2017 14:52:08 +0200 Subject: MDEV-12863 No table can be created after second encryption plugin attempted to load when deinitializing encryption plugins, disable server-wide encryption only if this plugin is the one that is used for encryption. --- sql/encryption.cc | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'sql') diff --git a/sql/encryption.cc b/sql/encryption.cc index a92296e8b66..52eab262570 100644 --- a/sql/encryption.cc +++ b/sql/encryption.cc @@ -98,19 +98,27 @@ int initialize_encryption_plugin(st_plugin_int *plugin) int finalize_encryption_plugin(st_plugin_int *plugin) { - encryption_handler.encryption_key_get_func= - (uint (*)(uint, uint, uchar*, uint*))no_key; - encryption_handler.encryption_key_get_latest_version_func= no_key; - encryption_handler.encryption_ctx_size_func= zero_size; + bool used= plugin_ref_to_int(encryption_manager) == plugin; + + if (used) + { + encryption_handler.encryption_key_get_func= + (uint (*)(uint, uint, uchar*, uint*))no_key; + encryption_handler.encryption_key_get_latest_version_func= no_key; + encryption_handler.encryption_ctx_size_func= zero_size; + } if (plugin && plugin->plugin->deinit && plugin->plugin->deinit(NULL)) { DBUG_PRINT("warning", ("Plugin '%s' deinit function returned error.", plugin->name.str)); } - if (encryption_manager) + + if (used) + { plugin_unlock(NULL, encryption_manager); - encryption_manager= 0; + encryption_manager= 0; + } return 0; } -- cgit v1.2.1 From bfa9990e333136ef205f8761785dacedb1eb7b35 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 2 Aug 2017 15:11:35 +0200 Subject: cleanup: simplify the assignment --- sql/mysqld.cc | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'sql') diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 592cf53b5b5..dcd45bcfc49 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4405,12 +4405,7 @@ static int init_common_variables() /* Fix back_log (back_log == 0 added for MySQL compatibility) */ if (back_log == 0 || IS_SYSVAR_AUTOSIZE(&back_log)) - { - if ((900 - 50) * 5 >= max_connections) - SYSVAR_AUTOSIZE(back_log, (50 + max_connections / 5)); - else - SYSVAR_AUTOSIZE(back_log, 900); - } + SYSVAR_AUTOSIZE(back_log, MY_MIN(900, (50 + max_connections / 5))); /* connections and databases needs lots of files */ { -- cgit v1.2.1 From 3ec96c18244b448b2adf30deb856e34907c12326 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 9 Aug 2017 20:35:33 +0200 Subject: MDEV-13370 Ambiguous behaviour regarding installation of header files install all server includes under /usr/include/mysql/server/ and C/C includes under /usr/include/mysql/ --- sql/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 7e7ed69ab46..eddbccfbb66 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -472,7 +472,7 @@ IF(WIN32) TARGET_LINK_LIBRARIES(mysql_upgrade_service mysys winservice) ENDIF(WIN32) -INSTALL(DIRECTORY . DESTINATION ${INSTALL_INCLUDEDIR}/private COMPONENT Development +INSTALL(DIRECTORY . DESTINATION ${INSTALL_INCLUDEDIR}/server/private COMPONENT Development FILES_MATCHING PATTERN "*.h" PATTERN share EXCLUDE PATTERN CMakeFiles EXCLUDE) -- cgit v1.2.1 From 34319403a510b92317d7bc8993f0d675e4841757 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 11 Aug 2017 16:17:08 +0200 Subject: fix a comment --- sql/mysqld.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/mysqld.cc b/sql/mysqld.cc index dcd45bcfc49..fce56e3f059 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1691,7 +1691,7 @@ static void close_connections(void) { DBUG_PRINT("quit",("Informing thread %ld that it's time to die", (ulong) tmp->thread_id)); - /* We skip slave threads & scheduler on this first loop through. */ + /* We skip slave threads on this first loop through. */ if (tmp->slave_thread) continue; -- cgit v1.2.1 From fc279d7ea263d8fd5f588b360a59c6891896f0b0 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 11 Aug 2017 18:36:51 +0200 Subject: InnoDB: test case to exploit a purge thread shutdown race condition execute queries after purge thread has exited, but the connection thread hasn't before c720e68f537 it used to crash --- sql/mysqld.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sql') diff --git a/sql/mysqld.cc b/sql/mysqld.cc index fce56e3f059..64b6384ca5b 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1695,6 +1695,10 @@ static void close_connections(void) if (tmp->slave_thread) continue; + /* cannot use 'continue' inside DBUG_EXECUTE_IF()... */ + if (DBUG_EVALUATE_IF("only_kill_system_threads", !tmp->system_thread, 0)) + continue; + #ifdef WITH_WSREP /* skip wsrep system threads as well */ if (WSREP(tmp) && (tmp->wsrep_exec_mode==REPL_RECV || tmp->wsrep_applier)) -- cgit v1.2.1 From 87f39bf8246961a44989a92767bc7a9a4d8e924e Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 12 Aug 2017 13:07:33 +0200 Subject: MDEV-8659 Conflicting declaration is accepted: INT SIGNED ZEROFILL don't allow arbitrary combinations of SIGNED/UNSIGNED/ZEROFILL --- sql/sql_yacc.yy | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) (limited to 'sql') diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 2d692e9e53b..43d4cf1e629 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1952,8 +1952,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); procedure_list procedure_list2 procedure_item field_def handler opt_generated_always opt_ignore opt_column opt_restrict - grant revoke set lock unlock string_list field_options field_option - field_opt_list opt_binary table_lock_list table_lock + grant revoke set lock unlock string_list field_options + opt_binary table_lock_list table_lock ref_list opt_match_clause opt_on_update_delete use opt_delete_options opt_delete_option varchar nchar nvarchar opt_outer table_list table_name table_alias_ref_list table_alias_ref @@ -6557,18 +6557,11 @@ precision: field_options: /* empty */ {} - | field_opt_list {} - ; - -field_opt_list: - field_opt_list field_option {} - | field_option {} - ; - -field_option: - SIGNED_SYM {} + | SIGNED_SYM {} | UNSIGNED { Lex->last_field->flags|= UNSIGNED_FLAG;} | ZEROFILL { Lex->last_field->flags|= UNSIGNED_FLAG | ZEROFILL_FLAG; } + | UNSIGNED ZEROFILL { Lex->last_field->flags|= UNSIGNED_FLAG | ZEROFILL_FLAG; } + | ZEROFILL UNSIGNED { Lex->last_field->flags|= UNSIGNED_FLAG | ZEROFILL_FLAG; } ; field_length: -- cgit v1.2.1 From 28ddc9b3bbbb56a3146779b1f0ccf42a6ef50f2b Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 12 Aug 2017 17:36:47 +0200 Subject: small cleanup --- sql/sql_table.cc | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) (limited to 'sql') diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 5c5f2d373c7..623ed45b1d2 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -7615,20 +7615,18 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, while ((drop=drop_it++)) { if (drop->type == Alter_drop::COLUMN && - !my_strcasecmp(system_charset_info,field->field_name, drop->name)) - { - /* Reset auto_increment value if it was dropped */ - if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER && - !(used_fields & HA_CREATE_USED_AUTO)) - { - create_info->auto_increment_value=0; - create_info->used_fields|=HA_CREATE_USED_AUTO; - } + !my_strcasecmp(system_charset_info, field->field_name, drop->name)) break; - } } if (drop) { + /* Reset auto_increment value if it was dropped */ + if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER && + !(used_fields & HA_CREATE_USED_AUTO)) + { + create_info->auto_increment_value=0; + create_info->used_fields|=HA_CREATE_USED_AUTO; + } if (table->s->tmp_table == NO_TMP_TABLE) (void) delete_statistics_for_column(thd, table, field); drop_it.remove(); @@ -8975,11 +8973,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, alter_info->requested_algorithm != Alter_info::ALTER_TABLE_ALGORITHM_INPLACE) || is_inplace_alter_impossible(table, create_info, alter_info) -#ifdef WITH_PARTITION_STORAGE_ENGINE - || (partition_changed && - !(table->s->db_type()->partition_flags() & HA_USE_AUTO_PARTITION)) -#endif - ) + || IF_PARTITIONING((partition_changed && + !(table->s->db_type()->partition_flags() & HA_USE_AUTO_PARTITION)), 0)) { if (alter_info->requested_algorithm == Alter_info::ALTER_TABLE_ALGORITHM_INPLACE) -- cgit v1.2.1 From 04b288ae47dec8bd1a41902889956c4b0d711cc5 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 12 Aug 2017 18:52:38 +0200 Subject: MDEV-11114 Cannot drop column referenced by CHECK constraint SQL Standard behavior for DROP COLUMN xxx RESTRICT: * If a constraint (UNIQUE or CHECK) uses only the dropped column, it's automatically dropped too. If it uses many columns - an error. --- sql/sql_table.cc | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'sql') diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 623ed45b1d2..dd425a2bbbc 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -7549,6 +7549,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, bool modified_primary_key= FALSE; Create_field *def; Field **f_ptr,*field; + MY_BITMAP *dropped_fields= NULL; // if it's NULL - no dropped fields DBUG_ENTER("mysql_prepare_alter_table"); /* @@ -7605,6 +7606,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, /* First collect all fields from table which isn't in drop_list */ + bitmap_clear_all(&table->tmp_set); for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++) { Alter_drop *drop; @@ -7630,6 +7632,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, if (table->s->tmp_table == NO_TMP_TABLE) (void) delete_statistics_for_column(thd, table, field); drop_it.remove(); + dropped_fields= &table->tmp_set; + bitmap_set_bit(dropped_fields, field->field_index); continue; } /* Check if field is changed */ @@ -7816,6 +7820,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, continue; } + const char *dropped_key_part= NULL; KEY_PART_INFO *key_part= key_info->key_part; key_parts.empty(); bool delete_index_stat= FALSE; @@ -7845,6 +7850,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, if (table->s->primary_key == i) modified_primary_key= TRUE; delete_index_stat= TRUE; + dropped_key_part= key_part_name; continue; // Field is removed } key_part_length= key_part->length; @@ -7927,6 +7933,11 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, key_type= Key::PRIMARY; else key_type= Key::UNIQUE; + if (dropped_key_part) + { + my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), dropped_key_part); + goto err; + } } else if (key_info->flags & HA_FULLTEXT) key_type= Key::FULLTEXT; @@ -7977,6 +7988,23 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, break; } } + /* see if the constraint depends on *only* on dropped fields */ + if (dropped_fields) + { + table->default_column_bitmaps(); + bitmap_clear_all(table->read_set); + check->expr->walk(&Item::register_field_in_read_map, 1, 0); + if (bitmap_is_subset(table->read_set, dropped_fields)) + drop= (Alter_drop*)1; + else if (bitmap_is_overlapping(dropped_fields, table->read_set)) + { + bitmap_intersect(table->read_set, dropped_fields); + uint field_nr= bitmap_get_first_set(table->read_set); + my_error(ER_BAD_FIELD_ERROR, MYF(0), + table->field[field_nr]->field_name, "CHECK"); + goto err; + } + } if (!drop) new_constraint_list.push_back(check, thd->mem_root); } -- cgit v1.2.1 From d07daa3125b295b6b30f72e788c11c1b998b5225 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 12 Aug 2017 18:54:05 +0200 Subject: MDEV-13313 JSON type alias is insufficiently compatible make JSON an alias for LONGTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin (same collation that item_jsonfunc.cc is using internally) --- sql/sql_yacc.yy | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 43d4cf1e629..5f956e02bcf 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -6478,8 +6478,11 @@ field_type: { $$.set(MYSQL_TYPE_SET); } | LONG_SYM opt_binary { $$.set(MYSQL_TYPE_MEDIUM_BLOB); } - | JSON_SYM opt_binary - { $$.set(MYSQL_TYPE_BLOB); } + | JSON_SYM + { + Lex->charset= &my_charset_utf8mb4_bin; + $$.set(MYSQL_TYPE_LONG_BLOB); + } ; spatial_type: -- cgit v1.2.1 From d924e0b993e76201a1670976860425ce73ecacf4 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 12 Aug 2017 19:09:03 +0200 Subject: MDEV-13375 back_log ignored doing SYSVAR_AUTOSIZE() because of back_log > max_connections enabled "autosized" flag, and that made IS_SYSVAR_AUTOSIZE() true, which triggered the second SYSVAR_AUTOSIZE. Remove back_log <= max_connections limit, back_log doesn't *always* have to be smaller than max_connections. --- sql/mysqld.cc | 2 -- 1 file changed, 2 deletions(-) (limited to 'sql') diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 64b6384ca5b..79e205219e1 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -9674,8 +9674,6 @@ static int get_options(int *argc_ptr, char ***argv_ptr) #endif /* Ensure that some variables are not set higher than needed */ - if (back_log > max_connections) - SYSVAR_AUTOSIZE(back_log, max_connections); if (thread_cache_size > max_connections) SYSVAR_AUTOSIZE(thread_cache_size, max_connections); -- cgit v1.2.1 From 399e14f066a4007f50c0060fe55f9b35949651ba Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 13 Aug 2017 01:08:30 +0200 Subject: MDEV-13435 Crash when selecting virtual columns generated using JSON functions don't allocate memory on thd->mem_root in every fix_fields(), do it once and reuse. --- sql/item_jsonfunc.cc | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'sql') diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index 88165c09426..c2a9ca28c99 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -643,17 +643,21 @@ error: static int alloc_tmp_paths(THD *thd, uint n_paths, - json_path_with_flags **paths,String **tmp_paths) + json_path_with_flags **paths, String **tmp_paths) { if (n_paths > 0) { - *paths= (json_path_with_flags *) alloc_root(thd->mem_root, - sizeof(json_path_with_flags) * n_paths); - *tmp_paths= (String *) alloc_root(thd->mem_root, sizeof(String) * n_paths); - if (*paths == 0 || *tmp_paths == 0) - return 1; + if (*tmp_paths == 0) + { + MEM_ROOT *root= thd->stmt_arena->mem_root; + *paths= (json_path_with_flags *) alloc_root(root, + sizeof(json_path_with_flags) * n_paths); + *tmp_paths= (String *) alloc_root(root, sizeof(String) * n_paths); + if (*paths == 0 || *tmp_paths == 0) + return 1; - bzero(*tmp_paths, sizeof(String) * n_paths); + bzero(*tmp_paths, sizeof(String) * n_paths); + } return 0; } @@ -687,7 +691,6 @@ void Item_json_str_multipath::cleanup() { for (uint i= get_n_paths(); i>0; i--) tmp_paths[i-1].free(); - tmp_paths= 0; } Item_str_func::cleanup(); } -- cgit v1.2.1 From b2af0ddcf95ade838e67595fd09e9c4a60efbb04 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 13 Aug 2017 19:12:36 +0200 Subject: enable innodb tests for virtual indexed columns (sic!) collateral changes: * remove a test from innodb_virtual_basic that is already present in gcol_keys_innodb * set thd->abort_on_warning for inplace alter, just like it's set for copy_data_between_tables - to have warnings converted into errors identically in all alter algorithms * don't ignore errors in TABLE::update_virtual_field --- sql/sql_table.cc | 10 ++++++---- sql/table.cc | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'sql') diff --git a/sql/sql_table.cc b/sql/sql_table.cc index dd425a2bbbc..1e2e7aedbd4 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -7179,6 +7179,7 @@ static bool mysql_inplace_alter_table(THD *thd, HA_CREATE_INFO *create_info= ha_alter_info->create_info; Alter_info *alter_info= ha_alter_info->alter_info; bool reopen_tables= false; + bool res; DBUG_ENTER("mysql_inplace_alter_table"); @@ -7313,11 +7314,12 @@ static bool mysql_inplace_alter_table(THD *thd, DEBUG_SYNC(thd, "alter_table_inplace_after_lock_downgrade"); THD_STAGE_INFO(thd, stage_alter_inplace); - if (table->file->ha_inplace_alter_table(altered_table, - ha_alter_info)) - { + /* We can abort alter table for any table type */ + thd->abort_on_warning= !ha_alter_info->ignore && thd->is_strict_mode(); + res= table->file->ha_inplace_alter_table(altered_table, ha_alter_info); + thd->abort_on_warning= false; + if (res) goto rollback; - } // Upgrade to EXCLUSIVE before commit. if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME)) diff --git a/sql/table.cc b/sql/table.cc index b03f64bc7e0..450e116080a 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -7468,7 +7468,7 @@ int TABLE::update_virtual_field(Field *vf) vf->vcol_info->expr->walk(&Item::update_vcol_processor, 0, &tmp_set); vf->vcol_info->expr->save_in_field(vf, 0); in_use->restore_active_arena(expr_arena, &backup_arena); - DBUG_RETURN(0); + DBUG_RETURN(in_use->is_error()); } -- cgit v1.2.1 From f066c89a972f8972c8ea5af9be1ee5e83fbbe372 Mon Sep 17 00:00:00 2001 From: =Ian Gilfillan Date: Thu, 10 Aug 2017 16:02:54 +0200 Subject: MDEV-8579 Expand system variable documentation --- sql/sys_vars.cc | 203 ++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 147 insertions(+), 56 deletions(-) (limited to 'sql') diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 9c27efc8ec3..e0b8b522610 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -370,7 +370,7 @@ static Sys_var_mybool Sys_automatic_sp_privileges( static Sys_var_ulong Sys_back_log( "back_log", "The number of outstanding connection requests " - "MariaDB can have. This comes into play when the main MySQL thread " + "MariaDB can have. This comes into play when the main MariaDB thread " "gets very many connection requests in a very short time", AUTO_SET READ_ONLY GLOBAL_VAR(back_log), CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 65535), DEFAULT(150), BLOCK_SIZE(1)); @@ -394,7 +394,7 @@ static Sys_var_ulonglong Sys_binlog_stmt_cache_size( "binlog_stmt_cache_size", "The size of the statement cache for " "updates to non-transactional engines for the binary log. " "If you often use statements updating a great number of rows, " - "you can increase this to get more performance", + "you can increase this to get more performance.", GLOBAL_VAR(binlog_stmt_cache_size), CMD_LINE(REQUIRED_ARG), VALID_RANGE(IO_SIZE, SIZE_T_MAX), DEFAULT(32768), BLOCK_SIZE(IO_SIZE)); @@ -809,7 +809,15 @@ export bool fix_delay_key_write(sys_var *self, THD *thd, enum_var_type type) } static const char *delay_key_write_names[]= { "OFF", "ON", "ALL", NullS }; static Sys_var_enum Sys_delay_key_write( - "delay_key_write", "Type of DELAY_KEY_WRITE", + "delay_key_write", "Specifies how MyISAM tables handles CREATE " + "TABLE DELAY_KEY_WRITE. If set to ON, the default, any DELAY KEY " + "WRITEs are honored. The key buffer is then flushed only when the " + "table closes, speeding up writes. MyISAM tables should be " + "automatically checked upon startup in this case, and " + "--external locking should not be used, as it can lead to index " + "corruption. If set to OFF, DELAY KEY WRITEs are ignored, while if " + "set to ALL, all new opened tables are treated as if created with " + "DELAY KEY WRITEs enabled.", GLOBAL_VAR(delay_key_write_options), CMD_LINE(OPT_ARG), delay_key_write_names, DEFAULT(DELAY_KEY_WRITE_ON), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), @@ -819,7 +827,7 @@ static Sys_var_ulong Sys_delayed_insert_limit( "delayed_insert_limit", "After inserting delayed_insert_limit rows, the INSERT DELAYED " "handler will check if there are any SELECT statements pending. " - "If so, it allows these to execute before continuing", + "If so, it allows these to execute before continuing.", GLOBAL_VAR(delayed_insert_limit), CMD_LINE(REQUIRED_ARG), VALID_RANGE(1, UINT_MAX), DEFAULT(DELAYED_LIMIT), BLOCK_SIZE(1)); @@ -2331,7 +2339,7 @@ static Sys_var_ulong Sys_optimizer_search_depth( "optimization, but may produce very bad query plans. If set to 0, " "the system will automatically pick a reasonable value; if set to " "63, the optimizer will switch to the original find_best search. " - "NOTE: The value 63 and its associated behaviour is deprecated", + "NOTE: The value 63 and its associated behaviour is deprecated.", SESSION_VAR(optimizer_search_depth), CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, MAX_TABLES+2), DEFAULT(MAX_TABLES+1), BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), @@ -2413,7 +2421,7 @@ static Sys_var_ulong Sys_preload_buff_size( static Sys_var_uint Sys_protocol_version( "protocol_version", - "The version of the client/server protocol used by the MySQL server", + "The version of the client/server protocol used by the MariaDB server", READ_ONLY GLOBAL_VAR(protocol_version), CMD_LINE_HELP_ONLY, VALID_RANGE(0, ~0), DEFAULT(PROTOCOL_VERSION), BLOCK_SIZE(1)); @@ -2864,7 +2872,7 @@ static Sys_var_enum Slave_exec_mode( "For example, in row based replication attempts to delete rows that " "doesn't exist will be ignored. " "In STRICT mode, replication will stop on any unexpected difference " - "between the master and the slave", + "between the master and the slave.", GLOBAL_VAR(slave_exec_mode_options), CMD_LINE(REQUIRED_ARG), slave_exec_mode_names, DEFAULT(SLAVE_EXEC_MODE_STRICT)); @@ -3350,14 +3358,17 @@ bool Sys_var_tx_read_only::session_update(THD *thd, set_var *var) static Sys_var_tx_read_only Sys_tx_read_only( - "tx_read_only", "Set default transaction access mode to read only.", + "tx_read_only", "Default transaction access mode. If set to OFF, " + "the default, access is read/write. If set to ON, access is read-only. " + "The SET TRANSACTION statement can also change the value of this variable. " + "See SET TRANSACTION and START TRANSACTION.", SESSION_VAR(tx_read_only), NO_CMD_LINE, DEFAULT(0), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_tx_read_only)); static Sys_var_ulonglong Sys_tmp_table_size( "tmp_table_size", - "If an internal in-memory temporary table exceeds this size, MySQL " - "will automatically convert it to an on-disk MyISAM or Aria table", + "If an internal in-memory temporary table exceeds this size, MariaDB " + "will automatically convert it to an on-disk MyISAM or Aria table.", SESSION_VAR(tmp_table_size), CMD_LINE(REQUIRED_ARG), VALID_RANGE(1024, (ulonglong)~(intptr)0), DEFAULT(16*1024*1024), BLOCK_SIZE(1)); @@ -3371,27 +3382,35 @@ static Sys_var_mybool Sys_timed_mutexes( static char *server_version_ptr; static Sys_var_charptr Sys_version( - "version", "Server version", + "version", "Server version number. It may also include a suffix " + "with configuration or build information. -debug indicates " + "debugging support was enabled on the server, and -log indicates " + "at least one of the binary log, general log or slow query log are " + "enabled, for example 10.1.1-MariaDB-mariadb1precise-log.", READ_ONLY GLOBAL_VAR(server_version_ptr), CMD_LINE_HELP_ONLY, IN_SYSTEM_CHARSET, DEFAULT(server_version)); static char *server_version_comment_ptr; static Sys_var_charptr Sys_version_comment( - "version_comment", "version_comment", + "version_comment", "Value of the COMPILATION_COMMENT option " + "specified by CMake when building MariaDB, for example " + "mariadb.org binary distribution.", READ_ONLY GLOBAL_VAR(server_version_comment_ptr), CMD_LINE_HELP_ONLY, IN_SYSTEM_CHARSET, DEFAULT(MYSQL_COMPILATION_COMMENT)); static char *server_version_compile_machine_ptr; static Sys_var_charptr Sys_version_compile_machine( - "version_compile_machine", "version_compile_machine", + "version_compile_machine", "The machine type or architecture " + "MariaDB was built on, for example i686.", READ_ONLY GLOBAL_VAR(server_version_compile_machine_ptr), CMD_LINE_HELP_ONLY, IN_SYSTEM_CHARSET, DEFAULT(DEFAULT_MACHINE)); static char *server_version_compile_os_ptr; static Sys_var_charptr Sys_version_compile_os( - "version_compile_os", "version_compile_os", + "version_compile_os", "Operating system that MariaDB was built " + "on, for example debian-linux-gnu.", READ_ONLY GLOBAL_VAR(server_version_compile_os_ptr), CMD_LINE_HELP_ONLY, IN_SYSTEM_CHARSET, DEFAULT(SYSTEM_TYPE)); @@ -3555,24 +3574,34 @@ static bool fix_autocommit(sys_var *self, THD *thd, enum_var_type type) } static Sys_var_bit Sys_autocommit( - "autocommit", "autocommit", + "autocommit", "If set to 1, the default, all queries are committed " + "immediately. If set to 0, they are only committed upon a COMMIT statement" + ", or rolled back with a ROLLBACK statement. If autocommit is set to 0, " + "and then changed to 1, all open transactions are immediately committed.", NO_SET_STMT SESSION_VAR(option_bits), NO_CMD_LINE, OPTION_AUTOCOMMIT, DEFAULT(TRUE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(fix_autocommit)); export sys_var *Sys_autocommit_ptr= &Sys_autocommit; // for sql_yacc.yy static Sys_var_mybool Sys_big_tables( - "big_tables", "Allow big result sets by saving all " - "temporary sets on file (Solves most 'table full' errors)", + "big_tables", "Old variable, which if set to 1, allows large result sets " + "by saving all temporary sets to disk, avoiding 'table full' errors. No " + "longer needed, as the server now handles this automatically. " + "sql_big_tables is a synonym.", SESSION_VAR(big_tables), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); static Sys_var_bit Sys_big_selects( - "sql_big_selects", "sql_big_selects", + "sql_big_selects", "If set to 0, MariaDB will not perform large SELECTs." + " See max_join_size for details. If max_join_size is set to anything but " + "DEFAULT, sql_big_selects is automatically set to 0. If sql_big_selects " + "is again set, max_join_size will be ignored.", SESSION_VAR(option_bits), NO_CMD_LINE, OPTION_BIG_SELECTS, DEFAULT(FALSE)); static Sys_var_bit Sys_log_off( - "sql_log_off", "sql_log_off", + "sql_log_off", "If set to 1 (0 is the default), no logging to the general " + "query log is done for the client. Only clients with the SUPER privilege " + "can update this variable.", NO_SET_STMT SESSION_VAR(option_bits), NO_CMD_LINE, OPTION_LOG_OFF, DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_has_super)); @@ -3629,50 +3658,80 @@ static bool check_sql_log_bin(sys_var *self, THD *thd, set_var *var) return FALSE; } -static Sys_var_mybool Sys_log_binlog( - "sql_log_bin", "Controls whether logging to the binary log is done", +static Sys_var_mybool Sys_log_binlog( + "sql_log_bin", "If set to 0 (1 is the default), no logging to the binary " + "log is done for the client. Only clients with the SUPER privilege can " + "update this variable. Can have unintended consequences if set globally, " + "see SET SQL_LOG_BIN. Starting MariaDB 10.1.7, this variable does not " + "affect the replication of events in a Galera cluster.", SESSION_VAR(sql_log_bin), NO_CMD_LINE, DEFAULT(TRUE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_sql_log_bin), ON_UPDATE(fix_sql_log_bin_after_update)); static Sys_var_bit Sys_sql_warnings( - "sql_warnings", "sql_warnings", + "sql_warnings", "If set to 1, single-row INSERTs will produce a string " + "containing warning information if a warning occurs.", SESSION_VAR(option_bits), NO_CMD_LINE, OPTION_WARNINGS, DEFAULT(FALSE)); static Sys_var_bit Sys_sql_notes( - "sql_notes", "sql_notes", + "sql_notes", "If set to 1, the default, warning_count is incremented each " + "time a Note warning is encountered. If set to 0, Note warnings are not " + "recorded. mysqldump has outputs to set this variable to 0 so that no " + "unnecessary increments occur when data is reloaded.", SESSION_VAR(option_bits), NO_CMD_LINE, OPTION_SQL_NOTES, DEFAULT(TRUE)); static Sys_var_bit Sys_auto_is_null( - "sql_auto_is_null", "sql_auto_is_null", + "sql_auto_is_null", "If set to 1, the query SELECT * FROM table_name WHERE " + "auto_increment_column IS NULL will return an auto-increment that has just " + "been successfully inserted, the same as the LAST_INSERT_ID() function. Some" + " ODBC programs make use of this IS NULL comparison.", SESSION_VAR(option_bits), NO_CMD_LINE, OPTION_AUTO_IS_NULL, DEFAULT(FALSE), NO_MUTEX_GUARD, IN_BINLOG); static Sys_var_bit Sys_safe_updates( - "sql_safe_updates", "sql_safe_updates", + "sql_safe_updates", "If set to 1, UPDATEs and DELETEs need either a key in " + "the WHERE clause, or a LIMIT clause, or else they will aborted. Prevents " + "the common mistake of accidentally deleting or updating every row in a table.", SESSION_VAR(option_bits), NO_CMD_LINE, OPTION_SAFE_UPDATES, DEFAULT(FALSE)); static Sys_var_bit Sys_buffer_results( - "sql_buffer_result", "sql_buffer_result", + "sql_buffer_result", "If set to 1 (0 is default), results from SELECT " + "statements are always placed into temporary tables. This can help the " + "server when it takes a long time to send the results to the client by " + "allowing the table locks to be freed early.", SESSION_VAR(option_bits), NO_CMD_LINE, OPTION_BUFFER_RESULT, DEFAULT(FALSE)); static Sys_var_bit Sys_quote_show_create( - "sql_quote_show_create", "sql_quote_show_create", + "sql_quote_show_create", "If set to 1, the default, the server will " + "quote identifiers for SHOW CREATE DATABASE, SHOW CREATE TABLE and " + "SHOW CREATE VIEW statements. Quoting is disabled if set to 0. Enable " + "to ensure replications works when identifiers require quoting.", SESSION_VAR(option_bits), NO_CMD_LINE, OPTION_QUOTE_SHOW_CREATE, DEFAULT(TRUE)); static Sys_var_bit Sys_foreign_key_checks( - "foreign_key_checks", "foreign_key_checks", + "foreign_key_checks", "If set to 1 (the default) foreign key constraints" + " (including ON UPDATE and ON DELETE behavior) InnoDB tables are checked," + " while if set to 0, they are not checked. 0 is not recommended for normal " + "use, though it can be useful in situations where you know the data is " + "consistent, but want to reload data in a different order from that that " + "specified by parent/child relationships. Setting this variable to 1 does " + "not retrospectively check for inconsistencies introduced while set to 0.", SESSION_VAR(option_bits), NO_CMD_LINE, REVERSE(OPTION_NO_FOREIGN_KEY_CHECKS), DEFAULT(TRUE), NO_MUTEX_GUARD, IN_BINLOG); static Sys_var_bit Sys_unique_checks( - "unique_checks", "unique_checks", + "unique_checks", "If set to 1, the default, secondary indexes in InnoDB " + "tables are performed. If set to 0, storage engines can (but are not " + "required to) assume that duplicate keys are not present in input data. " + "Set to 0 to speed up imports of large tables to InnoDB. The storage " + "engine will still issue a duplicate key error if it detects one, even " + "if set to 0.", SESSION_VAR(option_bits), NO_CMD_LINE, REVERSE(OPTION_RELAXED_UNIQUE_CHECKS), DEFAULT(TRUE), NO_MUTEX_GUARD, IN_BINLOG); @@ -3686,13 +3745,16 @@ static bool update_profiling(sys_var *self, THD *thd, enum_var_type type) } static Sys_var_bit Sys_profiling( - "profiling", "profiling", + "profiling", "If set to 1 (0 is default), statement profiling will be " + "enabled. See SHOW PROFILES and SHOW PROFILE.", NO_SET_STMT SESSION_VAR(option_bits), NO_CMD_LINE, OPTION_PROFILING, DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(update_profiling)); static Sys_var_ulong Sys_profiling_history_size( - "profiling_history_size", "Limit of query profiling memory", + "profiling_history_size", "Number of statements about which profiling " + "information is maintained. If set to 0, no profiles are stored. " + "See SHOW PROFILES.", NO_SET_STMT SESSION_VAR(profiling_history_size), CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 100), DEFAULT(15), BLOCK_SIZE(1)); #endif @@ -3726,7 +3788,11 @@ static bool check_skip_replication(sys_var *self, THD *thd, set_var *var) } static Sys_var_bit Sys_skip_replication( - "skip_replication", "skip_replication", + "skip_replication", "Changes are logged into the binary log with the " + "@@skip_replication flag set. Such events will not be replicated by " + "slaves that run with --replicate-events-marked-for-skip set different " + "from its default of REPLICATE. See Selectively skipping replication " + "of binlog events for more information.", NO_SET_STMT SESSION_ONLY(option_bits), NO_CMD_LINE, OPTION_SKIP_REPLICATION, DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG, @@ -4069,43 +4135,61 @@ static Sys_var_charptr Sys_slow_log_path( ON_CHECK(check_log_path), ON_UPDATE(fix_slow_log_file)); static Sys_var_have Sys_have_compress( - "have_compress", "have_compress", + "have_compress", "If the zlib compression library is accessible to the " + "server, this will be set to YES, otherwise it will be NO. The COMPRESS() " + "and UNCOMPRESS() functions will only be available if set to YES.", READ_ONLY GLOBAL_VAR(have_compress), NO_CMD_LINE); static Sys_var_have Sys_have_crypt( - "have_crypt", "have_crypt", + "have_crypt", "If the crypt() system call is available this variable will " + "be set to YES, otherwise it will be set to NO. If set to NO, the " + "ENCRYPT() function cannot be used.", READ_ONLY GLOBAL_VAR(have_crypt), NO_CMD_LINE); static Sys_var_have Sys_have_dlopen( - "have_dynamic_loading", "have_dynamic_loading", + "have_dynamic_loading", "If the server supports dynamic loading of plugins, " + "will be set to YES, otherwise will be set to NO.", READ_ONLY GLOBAL_VAR(have_dlopen), NO_CMD_LINE); static Sys_var_have Sys_have_geometry( - "have_geometry", "have_geometry", + "have_geometry", "If the server supports spatial data types, will be set to " + "YES, otherwise will be set to NO.", READ_ONLY GLOBAL_VAR(have_geometry), NO_CMD_LINE); static Sys_var_have Sys_have_openssl( - "have_openssl", "have_openssl", + "have_openssl", "Comparing have_openssl with have_ssl will indicate whether " + "YaSSL or openssl was used. If YaSSL, have_ssl will be YES, but have_openssl " + "will be NO.", READ_ONLY GLOBAL_VAR(have_openssl), NO_CMD_LINE); static Sys_var_have Sys_have_profiling( - "have_profiling", "have_profiling", + "have_profiling", "If statement profiling is available, will be set to YES, " + "otherwise will be set to NO. See SHOW PROFILES and SHOW PROFILE.", READ_ONLY GLOBAL_VAR(have_profiling), NO_CMD_LINE); static Sys_var_have Sys_have_query_cache( - "have_query_cache", "have_query_cache", + "have_query_cache", "If the server supports the query cache, will be set to " + "YES, otherwise will be set to NO.", READ_ONLY GLOBAL_VAR(have_query_cache), NO_CMD_LINE); static Sys_var_have Sys_have_rtree_keys( - "have_rtree_keys", "have_rtree_keys", + "have_rtree_keys", "If RTREE indexes (used for spatial indexes) " + "are available, will be set to YES, otherwise will be set to NO.", READ_ONLY GLOBAL_VAR(have_rtree_keys), NO_CMD_LINE); static Sys_var_have Sys_have_ssl( - "have_ssl", "have_ssl", + "have_ssl", "If the server supports secure connections, will be set to YES, " + "otherwise will be set to NO. If set to DISABLED, the server was compiled with " + "TLS support, but was not started with TLS support (see the mysqld options). " + "See also have_openssl.", READ_ONLY GLOBAL_VAR(have_ssl), NO_CMD_LINE); static Sys_var_have Sys_have_symlink( - "have_symlink", "have_symlink", + "have_symlink", "If symbolic link support is enabled, will be set to YES, " + "otherwise will be set to NO. Required for the INDEX DIRECTORY and DATA " + "DIRECTORY table options (see CREATE TABLE) and Windows symlink support. " + "Will be set to DISABLED if the server is started with the " + "--skip-symbolic-links option.", READ_ONLY GLOBAL_VAR(have_symlink), NO_CMD_LINE); static bool fix_log_state(sys_var *self, THD *thd, enum_var_type type); @@ -4113,7 +4197,7 @@ static bool fix_log_state(sys_var *self, THD *thd, enum_var_type type); static Sys_var_mybool Sys_general_log( "general_log", "Log connections and queries to a table or log file. " "Defaults logging to a file 'hostname'.log or a table mysql.general_log" - "if --log-output=TABLE is used", + "if --log-output=TABLE is used.", GLOBAL_VAR(opt_log), CMD_LINE(OPT_ARG), DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(fix_log_state)); @@ -4122,7 +4206,7 @@ static Sys_var_mybool Sys_slow_query_log( "slow_query_log", "Log slow queries to a table or log file. Defaults logging to a file " "'hostname'-slow.log or a table mysql.slow_log if --log-output=TABLE is " - "used. Must be enabled to activate other slow log options", + "used. Must be enabled to activate other slow log options.", SESSION_VAR(sql_log_slow), CMD_LINE(OPT_ARG), DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(fix_log_state)); @@ -4194,12 +4278,12 @@ static Sys_var_set Sys_log_output( static Sys_var_mybool Sys_log_slave_updates( "log_slave_updates", "Tells the slave to log the updates from " "the slave thread to the binary log. You will need to turn it on if " - "you plan to daisy-chain the slaves", + "you plan to daisy-chain the slaves.", READ_ONLY GLOBAL_VAR(opt_log_slave_updates), CMD_LINE(OPT_ARG), DEFAULT(0)); static Sys_var_charptr Sys_relay_log( - "relay_log", "The location and name to use for relay logs", + "relay_log", "The location and name to use for relay logs.", READ_ONLY GLOBAL_VAR(opt_relay_logname), CMD_LINE(REQUIRED_ARG), IN_FS_CHARSET, DEFAULT(0)); @@ -4210,7 +4294,7 @@ static Sys_var_charptr Sys_relay_log( */ static Sys_var_charptr Sys_relay_log_index( "relay_log_index", "The location and name to use for the file " - "that keeps a list of the last relay logs", + "that keeps a list of the last relay logs.", READ_ONLY GLOBAL_VAR(relay_log_index), NO_CMD_LINE, IN_FS_CHARSET, DEFAULT(0)); @@ -4238,20 +4322,20 @@ static Sys_var_charptr Sys_log_bin_basename( static Sys_var_charptr Sys_relay_log_info_file( "relay_log_info_file", "The location and name of the file that " - "remembers where the SQL replication thread is in the relay logs", + "remembers where the SQL replication thread is in the relay logs.", READ_ONLY GLOBAL_VAR(relay_log_info_file), CMD_LINE(REQUIRED_ARG), IN_FS_CHARSET, DEFAULT(0)); static Sys_var_mybool Sys_relay_log_purge( "relay_log_purge", "if disabled - do not purge relay logs. " - "if enabled - purge them as soon as they are no more needed", + "if enabled - purge them as soon as they are no more needed.", GLOBAL_VAR(relay_log_purge), CMD_LINE(OPT_ARG), DEFAULT(TRUE)); static Sys_var_mybool Sys_relay_log_recovery( "relay_log_recovery", "Enables automatic relay log recovery " "right after the database startup, which means that the IO Thread " "starts re-fetching from the master right after the last transaction " - "processed", + "processed.", GLOBAL_VAR(relay_log_recovery), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); @@ -4655,7 +4739,9 @@ static Sys_var_struct Sys_lc_time_names( NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_locale)); static Sys_var_tz Sys_time_zone( - "time_zone", "time_zone", + "time_zone", "The current time zone, used to initialize the time " + "zone for a client when it connects. Set to SYSTEM by default, in " + "which the client uses the system time zone value.", SESSION_VAR(time_zone), NO_CMD_LINE, DEFAULT(&default_tz), NO_MUTEX_GUARD, IN_BINLOG); @@ -4672,7 +4758,8 @@ static Sys_var_charptr Sys_wsrep_provider( ON_CHECK(wsrep_provider_check), ON_UPDATE(wsrep_provider_update)); static Sys_var_charptr Sys_wsrep_provider_options( - "wsrep_provider_options", "provider specific options", + "wsrep_provider_options", "Semicolon (;) separated list of wsrep " + "options (see wsrep_provider_options documentation).", PREALLOCATED GLOBAL_VAR(wsrep_provider_options), CMD_LINE(REQUIRED_ARG), IN_SYSTEM_CHARSET, DEFAULT(""), NO_MUTEX_GUARD, NOT_IN_BINLOG, @@ -4703,13 +4790,17 @@ static Sys_var_charptr Sys_wsrep_cluster_address ( ON_UPDATE(wsrep_cluster_address_update)); static Sys_var_charptr Sys_wsrep_node_name ( - "wsrep_node_name", "Node name", + "wsrep_node_name", "Name of this node. This name can be used in " + "wsrep_sst_donor as a preferred donor. Note that multiple nodes " + "in a cluster can have the same name.", PREALLOCATED GLOBAL_VAR(wsrep_node_name), CMD_LINE(REQUIRED_ARG), IN_SYSTEM_CHARSET, DEFAULT(glob_hostname), NO_MUTEX_GUARD, NOT_IN_BINLOG, wsrep_node_name_check, wsrep_node_name_update); static Sys_var_charptr Sys_wsrep_node_address ( - "wsrep_node_address", "Node address", + "wsrep_node_address", "Specifies the node's network address, in " + "the format ip address[:port]. Used in situations where autoguessing " + "is not reliable. As of MariaDB 10.1.8, supports IPv6.", PREALLOCATED GLOBAL_VAR(wsrep_node_address), CMD_LINE(REQUIRED_ARG), IN_SYSTEM_CHARSET, DEFAULT(""), NO_MUTEX_GUARD, NOT_IN_BINLOG, @@ -4927,7 +5018,7 @@ static Sys_var_mybool Sys_wsrep_slave_UK_checks( CMD_LINE(OPT_ARG), DEFAULT(FALSE)); static Sys_var_mybool Sys_wsrep_restart_slave( - "wsrep_restart_slave", "Should MySQL slave be restarted automatically, when node joins back to cluster", + "wsrep_restart_slave", "Should MariaDB slave be restarted automatically, when node joins back to cluster", GLOBAL_VAR(wsrep_restart_slave), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); static Sys_var_mybool Sys_wsrep_dirty_reads( @@ -4954,7 +5045,7 @@ static Sys_var_mybool Sys_wsrep_gtid_mode( static char *wsrep_patch_version_ptr; static Sys_var_charptr Sys_wsrep_patch_version( - "wsrep_patch_version", "wsrep patch version", + "wsrep_patch_version", "Wsrep patch version, for example wsrep_25.10.", READ_ONLY GLOBAL_VAR(wsrep_patch_version_ptr), CMD_LINE_HELP_ONLY, IN_SYSTEM_CHARSET, DEFAULT(WSREP_PATCH_VERSION)); -- cgit v1.2.1 From a28152aafcab34800652a8be014e7c6d6ddf7da4 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Tue, 15 Aug 2017 15:37:10 -0700 Subject: Fixed the bug mdev-13346. The bug was caused by a defect of the patch for the bug 11081. The patch was actually a port of the fix this bug from the mysql code line. Later a correction of this fix was added to the mysql code. Here's the comment this correction was provided with: Bug#16499751: Opening cursor on SELECT in stored procedure causes segfault This is a regression from the fix of bug#14740889. The fix started using another set of expressions as the source for the temporary table used for the materialized cursor. However, JOIN::make_tmp_tables_info() calls setup_copy_fields() which creates an Item_copy wrapper object on top of the function being selected. The Item_copy objects were not properly handled by create_tmp_table - they were simply ignored. This patch creates temporary table fields based on the underlying item of the Item_copy objects. The test case for the bug 13346 was taken from mdev-13380. --- sql/sql_select.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ba3760dd948..ce487205218 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -16572,7 +16572,12 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List &fields, Field **tmp_from_field=from_field; while ((item=li++)) { - Item::Type type=item->type(); + Item::Type type= item->type(); + if (type == Item::COPY_STR_ITEM) + { + item= ((Item_copy *)item)->get_item(); + type= item->type(); + } if (not_all_columns) { if (item->with_sum_func && type != Item::SUM_FUNC_ITEM) -- cgit v1.2.1 From a4885dde4ccec68bbb0268796f62e68e08ba4837 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 16 Aug 2017 18:44:17 +0200 Subject: MDEV-13535 Query on MyISAM table corrupts the table don't assume that the table always has a primary key, head->s->primary_key might be MAX_KEY, which won't start keyread. --- sql/opt_range.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/opt_range.cc b/sql/opt_range.cc index ec59c0acf86..c15810ba686 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -10889,13 +10889,13 @@ int read_keys_and_merge_scans(THD *thd, DBUG_ENTER("read_keys_and_merge"); /* We're going to just read rowids. */ - head->file->ha_start_keyread(head->s->primary_key); head->prepare_for_position(); cur_quick_it.rewind(); cur_quick= cur_quick_it++; bool first_quick= TRUE; DBUG_ASSERT(cur_quick != 0); + head->file->ha_start_keyread(cur_quick->index); /* We reuse the same instance of handler so we need to call both init and -- cgit v1.2.1 From c548fb0667ffe71d9387eaec342b1716fc4c9526 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 16 Aug 2017 19:18:39 +0200 Subject: MDEV-11240: Server crashes in check_view_single_update or Assertion `derived->table' failed in mysql_derived_merge_for_insert Before "merge" view shoud be inited to maintaing transitive attributes like "multitable". --- sql/sql_derived.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 6285a1810dd..bc5007e0880 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -520,6 +520,8 @@ bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived) derived->merge_underlying_list != 0)); if (derived->merged_for_insert) DBUG_RETURN(FALSE); + if (derived->init_derived(thd, FALSE)) + DBUG_RETURN(TRUE); if (derived->is_materialized_derived()) DBUG_RETURN(mysql_derived_prepare(thd, lex, derived)); if ((thd->lex->sql_command == SQLCOM_UPDATE_MULTI || @@ -537,8 +539,6 @@ bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived) DBUG_ASSERT(derived->table); } } - else - derived->table= derived->merge_underlying_list->table; DBUG_RETURN(FALSE); } -- cgit v1.2.1