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