diff options
Diffstat (limited to 'sql')
46 files changed, 462 insertions, 229 deletions
diff --git a/sql/debug_sync.cc b/sql/debug_sync.cc index e50ab0891ed..b1846bc48d5 100644 --- a/sql/debug_sync.cc +++ b/sql/debug_sync.cc @@ -1,4 +1,5 @@ /* Copyright (c) 2009, 2013, Oracle and/or its affiliates. + Copyright (c) 2013, 2020, MariaDB 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 @@ -319,7 +320,8 @@ static char *debug_sync_bmove_len(char *to, char *to_end, DBUG_ASSERT(to_end); DBUG_ASSERT(!length || from); set_if_smaller(length, (size_t) (to_end - to)); - memcpy(to, from, length); + if (length) + memcpy(to, from, length); return (to + length); } diff --git a/sql/item.cc b/sql/item.cc index 140eb5244ec..994d45a9dc3 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2018, Oracle and/or its affiliates. - Copyright (c) 2010, 2018, MariaDB Corporation + Copyright (c) 2010, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2332,8 +2332,6 @@ bool Item_func_or_sum::agg_item_set_converter(const DTCollation &coll, Item* conv= (*arg)->safe_charset_converter(thd, coll.collation); if (conv == *arg) continue; - if (!conv && ((*arg)->collation.repertoire == MY_REPERTOIRE_ASCII)) - conv= new (thd->mem_root) Item_func_conv_charset(thd, *arg, coll.collation, 1); if (!conv) { @@ -7212,7 +7210,6 @@ Item *find_producing_item(Item *item, st_select_lex *sel) DBUG_ASSERT(item->type() == Item::FIELD_ITEM || (item->type() == Item::REF_ITEM && ((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF)); - Item *producing_item; Item_field *field_item= NULL; Item_equal *item_equal= item->get_item_equal(); table_map tab_map= sel->master_unit()->derived->table->map; @@ -7234,6 +7231,7 @@ Item *find_producing_item(Item *item, st_select_lex *sel) List_iterator_fast<Item> li(sel->item_list); if (field_item) { + Item *producing_item= NULL; uint field_no= field_item->field->field_index; for (uint i= 0; i <= field_no; i++) producing_item= li++; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 03648a323d5..69c7eb33852 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -4153,8 +4153,11 @@ void Item_func_in::fix_after_pullout(st_select_lex *new_parent, Item **ref, eval_not_null_tables(NULL); } -static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y) +static int srtcmp_in(const void *cs_, const void *x_, const void *y_) { + const CHARSET_INFO *cs= static_cast<const CHARSET_INFO *>(cs_); + const String *x= static_cast<const String *>(x_); + const String *y= static_cast<const String *>(y_); return cs->coll->strnncollsp(cs, (uchar *) x->ptr(),x->length(), (uchar *) y->ptr(),y->length()); diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 645a3668ed8..1c3fafc0582 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2003, 2016, Oracle and/or its affiliates. - Copyright (c) 2011, 2016, MariaDB + Copyright (c) 2011, 2020, MariaDB 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 @@ -456,16 +456,18 @@ String *Item_func_boundary::val_str(String *str_value) DBUG_ASSERT(fixed == 1); String arg_val; String *swkb= args[0]->val_str(&arg_val); + + if ((null_value= args[0]->null_value)) + DBUG_RETURN(0); + Geometry_buffer buffer; - Geometry *g; uint32 srid= 0; Transporter trn(&res_receiver); - - if ((null_value= - args[0]->null_value || - !(g= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))) + + Geometry *g= Geometry::construct(&buffer, swkb->ptr(), swkb->length()); + if (!g) DBUG_RETURN(0); - + if (g->store_shapes(&trn)) goto mem_error; @@ -2389,12 +2391,15 @@ double Item_func_distance::val_real() MBR mbr1, mbr2; const char *c_end; - - if ((null_value= (args[0]->null_value || args[1]->null_value || - !(g1= Geometry::construct(&buffer1, res1->ptr(), res1->length())) || - !(g2= Geometry::construct(&buffer2, res2->ptr(), res2->length())) || - g1->get_mbr(&mbr1, &c_end) || - g2->get_mbr(&mbr2, &c_end)))) + if (args[0]->null_value || args[1]->null_value) + goto mem_error; + g1= Geometry::construct(&buffer1, res1->ptr(), res1->length()); + if (!g1) + goto mem_error; + g2= Geometry::construct(&buffer2, res2->ptr(), res2->length()); + if (!g2) + goto mem_error; + if (g1->get_mbr(&mbr1, &c_end) || g2->get_mbr(&mbr2, &c_end)) goto mem_error; mbr1.add_mbr(&mbr2); @@ -2543,7 +2548,7 @@ String *Item_func_pointonsurface::val_str(String *str) Geometry *g; MBR mbr; const char *c_end; - double UNINIT_VAR(px), UNINIT_VAR(py), x0, y0; + double UNINIT_VAR(px), UNINIT_VAR(py), x0, UNINIT_VAR(y0); String *result= 0; const Gcalc_scan_iterator::point *pprev= NULL; uint32 srid; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index df8761534a1..0bf21b63ac9 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -1198,11 +1198,19 @@ public: /* Conversion from and to "binary" is safe. Conversion to Unicode is safe. + Conversion from an expression with the ASCII repertoire + to any character set that can store characters U+0000..U+007F + is safe: + - All supported multibyte character sets can store U+0000..U+007F + - All supported 7bit character sets can store U+0000..U+007F + except those marked with MY_CS_NONASCII (e.g. swe7). Other kind of conversions are potentially lossy. */ safe= (args[0]->collation.collation == &my_charset_bin || cs == &my_charset_bin || - (cs->state & MY_CS_UNICODE)); + (cs->state & MY_CS_UNICODE) || + (args[0]->collation.repertoire == MY_REPERTOIRE_ASCII && + (cs->mbmaxlen > 1 || !(cs->state & MY_CS_NONASCII)))); } } bool is_json_type() { return args[0]->is_json_type(); } diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 23bdeacade9..816073ed5d3 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -145,6 +145,10 @@ public: Item_subselect(THD *thd); virtual subs_type substype() { return UNKNOWN_SUBS; } + bool is_exists_predicate() + { + return substype() == Item_subselect::EXISTS_SUBS; + } bool is_in_predicate() { return (substype() == Item_subselect::IN_SUBS || diff --git a/sql/item_windowfunc.cc b/sql/item_windowfunc.cc index 87dddbfb439..bb4a8a9f3af 100644 --- a/sql/item_windowfunc.cc +++ b/sql/item_windowfunc.cc @@ -234,7 +234,7 @@ bool Item_sum_hybrid_simple::fix_fields(THD *thd, Item **ref) { Item *item= args[i]; // 'item' can be changed during fix_fields - if ((!item->fixed && item->fix_fields(thd, args)) || + if ((!item->fixed && item->fix_fields(thd, args + i)) || (item= args[i])->check_cols(1)) return TRUE; with_window_func|= item->with_window_func; diff --git a/sql/log.cc b/sql/log.cc index cb484210c50..c784dc1c308 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -10403,7 +10403,8 @@ binlog_checksum_update(MYSQL_THD thd, struct st_mysql_sys_var *var, } -static int show_binlog_vars(THD *thd, SHOW_VAR *var, char *buff) +static int show_binlog_vars(THD *thd, SHOW_VAR *var, void *, + system_status_var *status_var, enum_var_type) { mysql_bin_log.set_status_variables(thd); var->type= SHOW_ARRAY; diff --git a/sql/log_event.cc b/sql/log_event.cc index 26c9cb6f9cb..5fd977da511 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2999,13 +2999,20 @@ log_event_print_value(IO_CACHE *file, const uchar *ptr, "Not enough metadata to display the value. "); break; + case MYSQL_TYPE_GEOMETRY: + strmake(typestr, "GEOMETRY", typestr_length); + if (!ptr) + goto return_null; + + length= uint4korr(ptr); + my_b_write_quoted(file, ptr + meta, length); + return length + meta; + default: { - char tmp[5]; - my_snprintf(tmp, sizeof(tmp), "%04x", meta); - my_b_printf(file, - "!! Don't know how to handle column type=%d meta=%d (%s)", - type, meta, tmp); + fprintf(stderr, + "\nError: Don't know how to handle column type: %d meta: %d (%04x)\n", + type, meta, meta); } break; } @@ -3579,7 +3586,7 @@ void Log_event::print_base64(IO_CACHE* file, #ifdef WHEN_FLASHBACK_REVIEW_READY ev->need_flashback_review= need_flashback_review; if (print_event_info->verbose) - ev->print_verbose(file, print_event_info); + ev->print_verbose(&print_event_info->tail_cache, print_event_info); else { IO_CACHE tmp_cache; @@ -3589,18 +3596,7 @@ void Log_event::print_base64(IO_CACHE* file, } #else if (print_event_info->verbose) - { - /* - Verbose event printout can't start before encoded data - got enquoted. This is done at this point though multi-row - statement remain vulnerable. - TODO: fix MDEV-10362 to remove this workaround. - */ - if (print_event_info->base64_output_mode != - BASE64_OUTPUT_DECODE_ROWS) - my_b_printf(file, "'%s\n", print_event_info->delimiter); - ev->print_verbose(file, print_event_info); - } + ev->print_verbose(&print_event_info->tail_cache, print_event_info); #endif delete ev; } @@ -11538,11 +11534,8 @@ void copy_cache_to_string_wrapped(IO_CACHE *cache, str_tmp.length= sprintf(str_tmp.str, fmt_frag, 1); ret.append(&str_tmp); ret.append(cache, uint32(cache->end_of_file - (cache_size/2 + 1))); - if (!is_verbose) - { - str_tmp.length= sprintf(str_tmp.str, fmt_delim, delimiter); - ret.append(&str_tmp); - } + str_tmp.length= sprintf(str_tmp.str, fmt_delim, delimiter); + ret.append(&str_tmp); str_tmp.length= sprintf(str_tmp.str, "BINLOG @binlog_fragment_0, @binlog_fragment_1%s\n", delimiter); ret.append(&str_tmp); @@ -11552,11 +11545,8 @@ void copy_cache_to_string_wrapped(IO_CACHE *cache, str_tmp.length= sprintf(str_tmp.str, str_binlog); ret.append(&str_tmp); ret.append(cache, (uint32) cache->end_of_file); - if (!is_verbose) - { - str_tmp.length= sprintf(str_tmp.str, fmt_delim, delimiter); - ret.append(&str_tmp); - } + str_tmp.length= sprintf(str_tmp.str, fmt_delim, delimiter); + ret.append(&str_tmp); } to->length= ret.length(); @@ -11605,6 +11595,7 @@ void Rows_log_event::print_helper(FILE *file, { IO_CACHE *const head= &print_event_info->head_cache; IO_CACHE *const body= &print_event_info->body_cache; + IO_CACHE *const tail= &print_event_info->tail_cache; #ifdef WHEN_FLASHBACK_REVIEW_READY IO_CACHE *const sql= &print_event_info->review_sql_cache; #endif @@ -11646,6 +11637,13 @@ void Rows_log_event::print_helper(FILE *file, print_event_info->verbose); output_buf.append(&tmp_str); my_free(tmp_str.str); + if (copy_event_cache_to_string_and_reinit(tail, &tmp_str)) + { + tail->error= -1; + return; + } + output_buf.append(&tmp_str); + my_free(tmp_str.str); } } #endif @@ -14316,6 +14314,7 @@ st_print_event_info::st_print_event_info() myf const flags = MYF(MY_WME | MY_NABP); open_cached_file(&head_cache, NULL, NULL, 0, flags); open_cached_file(&body_cache, NULL, NULL, 0, flags); + open_cached_file(&tail_cache, NULL, NULL, 0, flags); #ifdef WHEN_FLASHBACK_REVIEW_READY open_cached_file(&review_sql_cache, NULL, NULL, 0, flags); #endif diff --git a/sql/log_event.h b/sql/log_event.h index 1fae201057f..3fc44a9669f 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -848,18 +848,19 @@ typedef struct st_print_event_info ~st_print_event_info() { close_cached_file(&head_cache); close_cached_file(&body_cache); + close_cached_file(&tail_cache); #ifdef WHEN_FLASHBACK_REVIEW_READY close_cached_file(&review_sql_cache); #endif } bool init_ok() /* tells if construction was successful */ - { return my_b_inited(&head_cache) && my_b_inited(&body_cache) + { return my_b_inited(&head_cache) && my_b_inited(&body_cache) && + my_b_inited(&tail_cache) #ifdef WHEN_FLASHBACK_REVIEW_READY && my_b_inited(&review_sql_cache) #endif ; } - /* Settings on how to print the events */ bool short_form; enum_base64_output_mode base64_output_mode; @@ -885,6 +886,7 @@ typedef struct st_print_event_info */ IO_CACHE head_cache; IO_CACHE body_cache; + IO_CACHE tail_cache; #ifdef WHEN_FLASHBACK_REVIEW_READY /* Storing the SQL for reviewing */ IO_CACHE review_sql_cache; diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index b655d510bd5..2de316a4c55 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -1859,6 +1859,7 @@ void Old_rows_log_event::print_helper(FILE *file, { IO_CACHE *const head= &print_event_info->head_cache; IO_CACHE *const body= &print_event_info->body_cache; + IO_CACHE *const tail= &print_event_info->tail_cache; bool do_print_encoded= print_event_info->base64_output_mode != BASE64_OUTPUT_DECODE_ROWS && !print_event_info->short_form; @@ -1890,6 +1891,13 @@ void Old_rows_log_event::print_helper(FILE *file, print_event_info->verbose); output_buf.append(&tmp_str); my_free(tmp_str.str); + if (copy_event_cache_to_string_and_reinit(tail, &tmp_str)) + { + tail->error= -1; + return; + } + output_buf.append(&tmp_str); + my_free(tmp_str.str); } } #endif diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 44f8558e474..ad0b1d9c000 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3357,7 +3357,6 @@ void init_signals(void) sigemptyset(&sa.sa_mask); sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL); - my_init_stacktrace(); #if defined(__amiga__) sa.sa_handler=(void(*)())handle_fatal_signal; #else @@ -4081,7 +4080,8 @@ rpl_make_log_name(const char *opt, const char *ext) { DBUG_ENTER("rpl_make_log_name"); - DBUG_PRINT("enter", ("opt: %s, def: %s, ext: %s", opt, def, ext)); + DBUG_PRINT("enter", ("opt: %s, def: %s, ext: %s", opt ? opt : "(null)", + def, ext)); char buff[FN_REFLEN]; const char *base= opt ? opt : def; unsigned int options= @@ -6620,13 +6620,11 @@ void handle_connections_sockets() MYSQL_SOCKET sock= mysql_socket_invalid(); MYSQL_SOCKET new_sock= mysql_socket_invalid(); uint error_count=0; - CONNECT *connect; struct sockaddr_storage cAddr; int ip_flags __attribute__((unused))=0; int socket_flags __attribute__((unused))= 0; int extra_ip_flags __attribute__((unused))=0; int flags=0,retval; - bool is_unix_sock; #ifdef HAVE_POLL int socket_count= 0; struct pollfd fds[3]; // for ip_sock, unix_sock and extra_ip_sock @@ -6826,41 +6824,37 @@ void handle_connections_sockets() DBUG_PRINT("info", ("Creating CONNECT for new connection")); - if ((connect= new CONNECT())) + if (CONNECT *connect= new CONNECT()) { - is_unix_sock= (mysql_socket_getfd(sock) == - mysql_socket_getfd(unix_sock)); + const bool is_unix_sock= (mysql_socket_getfd(sock) == + mysql_socket_getfd(unix_sock)); - if (!(connect->vio= - mysql_socket_vio_new(new_sock, - is_unix_sock ? VIO_TYPE_SOCKET : - VIO_TYPE_TCPIP, - is_unix_sock ? VIO_LOCALHOST: 0))) + if ((connect->vio= + mysql_socket_vio_new(new_sock, + is_unix_sock ? VIO_TYPE_SOCKET : + VIO_TYPE_TCPIP, + is_unix_sock ? VIO_LOCALHOST: 0))) { - delete connect; - connect= 0; // Error handling below + if (is_unix_sock) + connect->host= my_localhost; + + if (mysql_socket_getfd(sock) == mysql_socket_getfd(extra_ip_sock)) + { + connect->extra_port= 1; + connect->scheduler= extra_thread_scheduler; + } + create_new_thread(connect); + continue; } - } - if (!connect) - { - /* Connect failure */ - (void) mysql_socket_shutdown(new_sock, SHUT_RDWR); - (void) mysql_socket_close(new_sock); - statistic_increment(aborted_connects,&LOCK_status); - statistic_increment(connection_errors_internal, &LOCK_status); - continue; + delete connect; } - if (is_unix_sock) - connect->host= my_localhost; - - if (mysql_socket_getfd(sock) == mysql_socket_getfd(extra_ip_sock)) - { - connect->extra_port= 1; - connect->scheduler= extra_thread_scheduler; - } - create_new_thread(connect); + /* Connect failure */ + (void) mysql_socket_shutdown(new_sock, SHUT_RDWR); + (void) mysql_socket_close(new_sock); + statistic_increment(aborted_connects,&LOCK_status); + statistic_increment(connection_errors_internal, &LOCK_status); } sd_notify(0, "STOPPING=1\n" "STATUS=Shutdown in progress\n"); @@ -8343,8 +8337,8 @@ show_ssl_get_server_not_after(THD *thd, SHOW_VAR *var, char *buff, #endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */ -static int show_default_keycache(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_default_keycache(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { struct st_data { KEY_CACHE_STATISTICS stats; @@ -8377,7 +8371,7 @@ static int show_default_keycache(THD *thd, SHOW_VAR *var, char *buff, v->name= 0; - DBUG_ASSERT((char*)(v+1) <= buff + SHOW_VAR_FUNC_BUFF_SIZE); + DBUG_ASSERT((char*)(v+1) <= static_cast<char*>(buff) + SHOW_VAR_FUNC_BUFF_SIZE); #undef set_one_keycache_var @@ -8401,8 +8395,8 @@ static int show_memory_used(THD *thd, SHOW_VAR *var, char *buff, #ifndef DBUG_OFF -static int debug_status_func(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int debug_status_func(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { #define add_var(X,Y,Z) \ v->name= X; \ diff --git a/sql/net_serv.cc b/sql/net_serv.cc index dc24360851e..076d26dee3d 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. - Copyright (c) 2012, 2018, MariaDB Corporation. + Copyright (c) 2012, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -604,7 +604,8 @@ net_write_buff(NET *net, const uchar *packet, ulong len) return net_real_write(net, packet, len) ? 1 : 0; /* Send out rest of the blocks as full sized blocks */ } - memcpy((char*) net->write_pos,packet,len); + if (len) + memcpy((char*) net->write_pos,packet,len); net->write_pos+= len; return 0; } diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 6a5f1c9f750..cd58202ef5f 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1852,6 +1852,9 @@ SEL_ARG::SEL_ARG(SEL_ARG &arg) :Sql_alloc() next_key_part=arg.next_key_part; max_part_no= arg.max_part_no; use_count=1; elements=1; + next= 0; + if (next_key_part) + ++next_key_part->use_count; } @@ -7555,13 +7558,15 @@ SEL_TREE *Item_bool_func::get_full_func_mm_tree(RANGE_OPT_PARAM *param, table_map param_comp= ~(param->prev_tables | param->read_tables | param->current_table); #ifdef HAVE_SPATIAL - Field::geometry_type sav_geom_type; - const bool geometry= field_item->field->type() == MYSQL_TYPE_GEOMETRY; - if (geometry) + Field::geometry_type sav_geom_type= Field::GEOM_GEOMETRY, *geom_type= + field_item->field->type() == MYSQL_TYPE_GEOMETRY + ? &(static_cast<Field_geom*>(field_item->field))->geom_type + : NULL; + if (geom_type) { - sav_geom_type= ((Field_geom*) field_item->field)->geom_type; + sav_geom_type= *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; + *geom_type= Field::GEOM_GEOMETRY; } #endif /*HAVE_SPATIAL*/ @@ -7592,9 +7597,9 @@ SEL_TREE *Item_bool_func::get_full_func_mm_tree(RANGE_OPT_PARAM *param, } #ifdef HAVE_SPATIAL - if (geometry) + if (geom_type) { - ((Field_geom*) field_item->field)->geom_type= sav_geom_type; + *geom_type= sav_geom_type; } #endif /*HAVE_SPATIAL*/ DBUG_RETURN(ftree); @@ -8867,9 +8872,15 @@ tree_or(RANGE_OPT_PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2) } bool no_imerge_from_ranges= FALSE; + SEL_TREE *rt1= tree1; + SEL_TREE *rt2= tree2; /* Build the range part of the tree for the formula (1) */ if (sel_trees_can_be_ored(param, tree1, tree2, &ored_keys)) { + if (no_merges1) + rt1= new SEL_TREE(tree1, TRUE, param); + if (no_merges2) + rt2= new SEL_TREE(tree2, TRUE, param); bool must_be_ored= sel_trees_must_be_ored(param, tree1, tree2, ored_keys); no_imerge_from_ranges= must_be_ored; @@ -8927,12 +8938,6 @@ tree_or(RANGE_OPT_PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2) else if (!no_ranges1 && !no_ranges2 && !no_imerge_from_ranges) { /* Build the imerge part of the tree for the formula (1) */ - SEL_TREE *rt1= tree1; - SEL_TREE *rt2= tree2; - if (no_merges1) - rt1= new SEL_TREE(tree1, TRUE, param); - if (no_merges2) - rt2= new SEL_TREE(tree2, TRUE, param); if (!rt1 || !rt2 || result->merges.push_back(imerge_from_ranges) || imerge_from_ranges->or_sel_tree(param, rt1) || @@ -9595,10 +9600,11 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2) if (!tmp->next_key_part) { + SEL_ARG *key2_next= key2->next; if (key2->use_count) { SEL_ARG *key2_cpy= new SEL_ARG(*key2); - if (key2_cpy) + if (!key2_cpy) return 0; key2= key2_cpy; } @@ -9619,7 +9625,7 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2) Move on to next range in key2 */ key2->increment_use_count(-1); // Free not used tree - key2=key2->next; + key2=key2_next; continue; } else diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 45aa625389d..fec4e8b2828 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2010, 2019, MariaDB + Copyright (c) 2010, 2020, MariaDB 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 @@ -2634,16 +2634,11 @@ bool find_eq_ref_candidate(TABLE *table, table_map sj_inner_tables) do { uint key= keyuse->key; - KEY *keyinfo; key_part_map bound_parts= 0; - bool is_excluded_key= keyuse->is_for_hash_join(); - if (!is_excluded_key) - { - keyinfo= table->key_info + key; - is_excluded_key= !MY_TEST(keyinfo->flags & HA_NOSAME); - } - if (!is_excluded_key) + if (!keyuse->is_for_hash_join() && + (table->key_info[key].flags & HA_NOSAME)) { + KEY *keyinfo= table->key_info + key; do /* For all equalities on all key parts */ { /* diff --git a/sql/protocol.cc b/sql/protocol.cc index aa795b9d12a..de6d1b96f76 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2012, Oracle and/or its affiliates. - Copyright (c) 2008, 2012, Monty Program Ab + Copyright (c) 2008, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -58,7 +58,8 @@ bool Protocol_binary::net_store_data(const uchar *from, size_t length) packet->realloc(packet_length+9+length)) return 1; uchar *to= net_store_length((uchar*) packet->ptr()+packet_length, length); - memcpy(to,from,length); + if (length) + memcpy(to,from,length); packet->length((uint) (to+length-(uchar*) packet->ptr())); return 0; } @@ -715,7 +716,8 @@ void net_send_progress_packet(THD *thd) uchar *net_store_data(uchar *to, const uchar *from, size_t length) { to=net_store_length_fast(to,length); - memcpy(to,from,length); + if (length) + memcpy(to,from,length); return to+length; } diff --git a/sql/records.cc b/sql/records.cc index 6a611d46ca4..8a152cda4c2 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -320,12 +320,9 @@ bool init_read_record(READ_RECORD *info,THD *thd, TABLE *table, void end_read_record(READ_RECORD *info) -{ /* free cache if used */ - if (info->cache) - { - my_free_lock(info->cache); - info->cache=0; - } +{ + /* free cache if used */ + free_cache(info); if (info->table) { if (info->table->is_created()) @@ -336,6 +333,17 @@ void end_read_record(READ_RECORD *info) } } + +void free_cache(READ_RECORD *info) +{ + if (info->cache) + { + my_free_lock(info->cache); + info->cache=0; + } +} + + static int rr_handle_error(READ_RECORD *info, int error) { if (info->thd->killed) diff --git a/sql/records.h b/sql/records.h index b5f04dbd161..dd63d3608bb 100644 --- a/sql/records.h +++ b/sql/records.h @@ -30,6 +30,7 @@ class SORT_INFO; struct READ_RECORD; void end_read_record(READ_RECORD *info); +void free_cache(READ_RECORD *info); /** A context for reading through a single table using a chosen access method: diff --git a/sql/rpl_filter.cc b/sql/rpl_filter.cc index 4c4b56f591f..2548dc92d7b 100644 --- a/sql/rpl_filter.cc +++ b/sql/rpl_filter.cc @@ -349,14 +349,20 @@ Rpl_filter::set_do_table(const char* table_spec) int status; if (do_table_inited) - my_hash_reset(&do_table); + { + my_hash_free(&do_table); + do_table_inited= 0; + } status= parse_filter_rule(table_spec, &Rpl_filter::add_do_table); - if (!do_table.records) + if (do_table_inited && status) { - my_hash_free(&do_table); - do_table_inited= 0; + if (!do_table.records) + { + my_hash_free(&do_table); + do_table_inited= 0; + } } return status; @@ -369,14 +375,20 @@ Rpl_filter::set_ignore_table(const char* table_spec) int status; if (ignore_table_inited) - my_hash_reset(&ignore_table); + { + my_hash_free(&ignore_table); + ignore_table_inited= 0; + } status= parse_filter_rule(table_spec, &Rpl_filter::add_ignore_table); - if (!ignore_table.records) + if (ignore_table_inited && status) { - my_hash_free(&ignore_table); - ignore_table_inited= 0; + if (!ignore_table.records) + { + my_hash_free(&ignore_table); + ignore_table_inited= 0; + } } return status; @@ -411,14 +423,20 @@ Rpl_filter::set_wild_do_table(const char* table_spec) int status; if (wild_do_table_inited) + { free_string_array(&wild_do_table); + wild_do_table_inited= 0; + } status= parse_filter_rule(table_spec, &Rpl_filter::add_wild_do_table); - if (!wild_do_table.elements) + if (wild_do_table_inited && status) { - delete_dynamic(&wild_do_table); - wild_do_table_inited= 0; + if (!wild_do_table.elements) + { + delete_dynamic(&wild_do_table); + wild_do_table_inited= 0; + } } return status; @@ -431,14 +449,20 @@ Rpl_filter::set_wild_ignore_table(const char* table_spec) int status; if (wild_ignore_table_inited) + { free_string_array(&wild_ignore_table); + wild_ignore_table_inited= 0; + } status= parse_filter_rule(table_spec, &Rpl_filter::add_wild_ignore_table); - if (!wild_ignore_table.elements) + if (wild_ignore_table_inited && status) { - delete_dynamic(&wild_ignore_table); - wild_ignore_table_inited= 0; + if (!wild_ignore_table.elements) + { + delete_dynamic(&wild_ignore_table); + wild_ignore_table_inited= 0; + } } return status; diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 8db992c7501..4bb1ae951af 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -1800,9 +1800,10 @@ ER_WRONG_AUTO_KEY 42000 S1009 slo "Môžete mať iba jedno AUTO pole a to musí byť definované ako kľúč" spa "Puede ser solamente un campo automatico y este debe ser definido como una clave" swe "Det får finnas endast ett AUTO_INCREMENT-fält och detta måste vara en nyckel" - ukr "Невірне визначення таблиці; Може бути лише один автоматичний стовбець, що повинен бути визначений як ключ" + ukr "Хибне визначення таблиці; Може бути лише один автоматичний стовбець, що повинен бути визначений як ключ" ER_BINLOG_CANT_DELETE_GTID_DOMAIN eng "Could not delete gtid domain. Reason: %s." + ukr "Не можу видалити домен gtid. Причина: %s." ER_NORMAL_SHUTDOWN cze "%s (%s): normální ukončení" dan "%s (%s): Normal nedlukning" @@ -2203,6 +2204,7 @@ ER_INSERT_INFO ER_UPDATE_TABLE_USED eng "Table '%-.192s' is specified twice, both as a target for '%s' and as a separate source for data" swe "Table '%-.192s' är använd två gånger. Både för '%s' och för att hämta data" + ukr "Таблиця '%-.192s' вказується двічі, як цільова для '%s', так і як окреме джерело даних" ER_NO_SUCH_THREAD cze "Neznámá identifikace threadu: %lu" dan "Ukendt tråd id: %lu" @@ -2824,6 +2826,7 @@ ER_WRONG_OUTER_JOIN 42000 ER_NULL_COLUMN_IN_INDEX 42000 eng "Table handler doesn't support NULL in given index. Please change column '%-.192s' to be NOT NULL or use another handler" swe "Tabell hanteraren kan inte indexera NULL kolumner för den givna index typen. Ändra '%-.192s' till NOT NULL eller använd en annan hanterare" + ukr "Вказівник таблиці не підтримує NULL у зазначенному індексі. Будь ласка, зменіть стовпчик '%-.192s' на NOT NULL або використайте інший вказівник таблиці." ER_CANT_FIND_UDF cze "Nemohu načíst funkci '%-.192s'" dan "Kan ikke læse funktionen '%-.192s'" @@ -3244,25 +3247,25 @@ ER_NONEXISTING_GRANT 42000 swe "Det finns inget privilegium definierat för användare '%-.48s' på '%-.64s'" ukr "Повноважень не визначено для користувача '%-.48s' з хосту '%-.64s'" ER_TABLEACCESS_DENIED_ERROR 42000 - cze "%-.32s příkaz nepřístupný pro uživatele: '%s'@'%s' pro tabulku '%-.192s'" - dan "%-.32s-kommandoen er ikke tilladt for brugeren '%s'@'%s' for tabellen '%-.192s'" - nla "%-.32s commando geweigerd voor gebruiker: '%s'@'%s' voor tabel '%-.192s'" - eng "%-.32s command denied to user '%s'@'%s' for table '%-.192s'" - jps "コマンド %-.32s は ユーザー '%s'@'%s' ,テーブル '%-.192s' に対して許可されていません", - est "%-.32s käsk ei ole lubatud kasutajale '%s'@'%s' tabelis '%-.192s'" - fre "La commande '%-.32s' est interdite à l'utilisateur: '%s'@'%s' sur la table '%-.192s'" - ger "%-.32s Befehl nicht erlaubt für Benutzer '%s'@'%s' auf Tabelle '%-.192s'" - hun "%-.32s parancs a '%s'@'%s' felhasznalo szamara nem engedelyezett a '%-.192s' tablaban" - ita "Comando %-.32s negato per l'utente: '%s'@'%s' sulla tabella '%-.192s'" - jpn "コマンド %-.32s は ユーザー '%s'@'%s' ,テーブル '%-.192s' に対して許可されていません" - kor "'%-.32s' 명령은 다음 사용자에게 거부되었습니다. : '%s'@'%s' for 테이블 '%-.192s'" - por "Comando '%-.32s' negado para o usuário '%s'@'%s' na tabela '%-.192s'" - rum "Comanda %-.32s interzisa utilizatorului: '%s'@'%s' pentru tabela '%-.192s'" - rus "Команда %-.32s запрещена пользователю '%s'@'%s' для таблицы '%-.192s'" - serbian "%-.32s komanda zabranjena za korisnika '%s'@'%s' za tabelu '%-.192s'" - spa "%-.32s comando negado para usuario: '%s'@'%s' para tabla '%-.192s'" - swe "%-.32s ej tillåtet för '%s'@'%s' för tabell '%-.192s'" - ukr "%-.32s команда заборонена користувачу: '%s'@'%s' у таблиці '%-.192s'" + cze "%-.100T příkaz nepřístupný pro uživatele: '%s'@'%s' pro tabulku '%-.192s'" + dan "%-.100T-kommandoen er ikke tilladt for brugeren '%s'@'%s' for tabellen '%-.192s'" + nla "%-.100T commando geweigerd voor gebruiker: '%s'@'%s' voor tabel '%-.192s'" + eng "%-.100T command denied to user '%s'@'%s' for table '%-.192s'" + jps "コマンド %-.100T は ユーザー '%s'@'%s' ,テーブル '%-.192s' に対して許可されていません", + est "%-.100T käsk ei ole lubatud kasutajale '%s'@'%s' tabelis '%-.192s'" + fre "La commande '%-.100T' est interdite à l'utilisateur: '%s'@'%s' sur la table '%-.192s'" + ger "%-.100T Befehl nicht erlaubt für Benutzer '%s'@'%s' auf Tabelle '%-.192s'" + hun "%-.100T parancs a '%s'@'%s' felhasznalo szamara nem engedelyezett a '%-.192s' tablaban" + ita "Comando %-.100T negato per l'utente: '%s'@'%s' sulla tabella '%-.192s'" + jpn "コマンド %-.100T は ユーザー '%s'@'%s' ,テーブル '%-.192s' に対して許可されていません" + kor "'%-.100T' 명령은 다음 사용자에게 거부되었습니다. : '%s'@'%s' for 테이블 '%-.192s'" + por "Comando '%-.100T' negado para o usuário '%s'@'%s' na tabela '%-.192s'" + rum "Comanda %-.100T interzisa utilizatorului: '%s'@'%s' pentru tabela '%-.192s'" + rus "Команда %-.100T запрещена пользователю '%s'@'%s' для таблицы '%-.192s'" + serbian "%-.100T komanda zabranjena za korisnika '%s'@'%s' za tabelu '%-.192s'" + spa "%-.100T comando negado para usuario: '%s'@'%s' para tabla '%-.192s'" + swe "%-.100T ej tillåtet för '%s'@'%s' för tabell '%-.192s'" + ukr "%-.100T команда заборонена користувачу: '%s'@'%s' у таблиці '%-.192s'" ER_COLUMNACCESS_DENIED_ERROR 42000 cze "%-.32s příkaz nepřístupný pro uživatele: '%s'@'%s' pro sloupec '%-.192s' v tabulce '%-.192s'" dan "%-.32s-kommandoen er ikke tilladt for brugeren '%s'@'%s' for kolonne '%-.192s' in tabellen '%-.192s'" @@ -4314,6 +4317,7 @@ ER_MASTER_INFO jpn "'master info '%.*s''構造体の初期化ができませんでした。MariaDBエラーログでエラーメッセージを確認してください。" serbian "Nisam mogao da inicijalizujem informacionu strukturu glavnog servera, proverite da li imam privilegije potrebne za pristup file-u 'master.info' '%.*s'" swe "Kunde inte initialisera replikationsstrukturerna för '%.*s'. See MariaDB fel fil för mera information" + ukr "Інформаційна структура з'єднання головного і підлеглого (master.info) для '%.*s' не може бути ініціалізована" ER_SLAVE_THREAD dan "Kunne ikke danne en slave-tråd; check systemressourcerne" nla "Kon slave thread niet aanmaken, controleer systeem resources" @@ -4478,6 +4482,7 @@ ER_UNION_TABLES_IN_DIFFERENT_DIR serbian "Pogrešna definicija tabele; sve 'MERGE' tabele moraju biti u istoj bazi podataka" spa "Incorrecta definición de la tabla; Todas las tablas MERGE deben estar en el mismo banco de datos" swe "Felaktig tabelldefinition; alla tabeller i en MERGE-tabell måste vara i samma databas" + ukr "Хибне визначення таблиці; всі MERGE-таблиці повинні належити до однієї бази ланних." ER_LOCK_DEADLOCK 40001 nla "Deadlock gevonden tijdens lock-aanvraag poging; Probeer herstart van de transactie" eng "Deadlock found when trying to get lock; try restarting transaction" @@ -4491,6 +4496,7 @@ ER_LOCK_DEADLOCK 40001 serbian "Unakrsno zaključavanje pronađeno kada sam pokušao da dobijem pravo na zaključavanje; Probajte da restartujete transakciju" spa "Encontrado deadlock cuando tentando obtener el bloqueo; Tente recomenzar la transición" swe "Fick 'DEADLOCK' vid låsförsök av block/rad. Försök att starta om transaktionen" + ukr "Взаємне блокування знайдено під час спроби отримати блокування; спробуйте перезапустити транзакцію." ER_TABLE_CANT_HANDLE_FT nla "Het gebruikte tabel type (%s) ondersteund geen FULLTEXT indexen" eng "The storage engine %s doesn't support FULLTEXT indexes" @@ -4517,6 +4523,7 @@ ER_CANNOT_ADD_FOREIGN serbian "Ne mogu da dodam proveru spoljnog ključa" spa "No puede adicionar clave extranjera constraint" swe "Kan inte lägga till 'FOREIGN KEY constraint'" + ukr "Не можу додати обмеження зовнішнього ключа" ER_NO_REFERENCED_ROW 23000 nla "Kan onderliggende rij niet toevoegen: foreign key beperking gefaald" eng "Cannot add or update a child row: a foreign key constraint fails" @@ -4531,6 +4538,7 @@ ER_NO_REFERENCED_ROW 23000 rus "Невозможно добавить или обновить дочернюю строку: проверка ограничений внешнего ключа не выполняется" spa "No puede adicionar una línea hijo: falla de clave extranjera constraint" swe "FOREIGN KEY-konflikt: Kan inte skriva barn" + ukr "Не вдається додати або оновити дочірній рядок: невдала перевірка обмеження зовнішнього ключа" ER_ROW_IS_REFERENCED 23000 eng "Cannot delete or update a parent row: a foreign key constraint fails" fre "Impossible de supprimer un enregistrement père : une constrainte externe l'empèche" diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index ec784bc6df4..0c50a251d26 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1748,15 +1748,13 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) } if (table->vfield) { - my_bool abort_on_warning= thd->abort_on_warning; /* We have not yet called update_virtual_fields(VOL_UPDATE_FOR_READ) in handler methods for the just read row in record[1]. */ table->move_fields(table->field, table->record[1], table->record[0]); - thd->abort_on_warning= 0; - table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_REPLACE); - thd->abort_on_warning= abort_on_warning; + if (table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_REPLACE)) + goto err; table->move_fields(table->field, table->record[0], table->record[1]); } if (info->handle_duplicates == DUP_UPDATE) diff --git a/sql/sql_plugin_services.ic b/sql/sql_plugin_services.ic index 20113444b64..43fe540731e 100644 --- a/sql/sql_plugin_services.ic +++ b/sql/sql_plugin_services.ic @@ -184,7 +184,8 @@ static struct wsrep_service_st wsrep_handler = { wsrep_trx_order_before, wsrep_unlock_rollback, wsrep_set_data_home_dir, - wsrep_thd_is_applier + wsrep_thd_is_applier, + wsrep_report_bf_lock_wait }; static struct thd_specifics_service_st thd_specifics_handler= diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 721b6799ed3..4af8ebc2dd8 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -3862,6 +3862,7 @@ bool mysql_show_binlog_events(THD* thd) { Protocol *protocol= thd->protocol; List<Item> field_list; + char errmsg_buf[MYSYS_ERRMSG_SIZE]; const char *errmsg = 0; bool ret = TRUE; /* @@ -3876,6 +3877,9 @@ bool mysql_show_binlog_events(THD* thd) Master_info *mi= 0; LOG_INFO linfo; LEX_MASTER_INFO *lex_mi= &thd->lex->mi; + enum enum_binlog_checksum_alg checksum_alg; + my_off_t binlog_size; + MY_STAT s; DBUG_ENTER("mysql_show_binlog_events"); @@ -3924,10 +3928,6 @@ bool mysql_show_binlog_events(THD* thd) mi= 0; } - /* Validate user given position using checksum */ - if (lex_mi->pos == pos && !opt_master_verify_checksum) - verify_checksum_once= true; - unit->set_limit(thd->lex->current_select); limit_start= unit->offset_limit_cnt; limit_end= unit->select_limit_cnt; @@ -3951,6 +3951,17 @@ bool mysql_show_binlog_events(THD* thd) if ((file=open_binlog(&log, linfo.log_file_name, &errmsg)) < 0) goto err; + my_stat(linfo.log_file_name, &s, MYF(0)); + binlog_size= s.st_size; + if (lex_mi->pos > binlog_size) + { + sprintf(errmsg_buf, "Invalid pos specified. Requested from pos:%llu is " + "greater than actual file size:%lu\n", lex_mi->pos, + (ulong)s.st_size); + errmsg= errmsg_buf; + goto err; + } + /* to account binlog event header size */ @@ -4002,7 +4013,43 @@ bool mysql_show_binlog_events(THD* thd) } } - my_b_seek(&log, pos); + if (lex_mi->pos > BIN_LOG_HEADER_SIZE) + { + checksum_alg= description_event->checksum_alg; + /* Validate user given position using checksum */ + if (checksum_alg != BINLOG_CHECKSUM_ALG_OFF && + checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF) + { + if (!opt_master_verify_checksum) + verify_checksum_once= true; + my_b_seek(&log, pos); + } + else + { + my_off_t cur_pos= my_b_tell(&log); + ulong next_event_len= 0; + uchar buff[IO_SIZE]; + while (cur_pos < pos) + { + my_b_seek(&log, cur_pos + EVENT_LEN_OFFSET); + if (my_b_read(&log, (uchar *)buff, sizeof(next_event_len))) + { + mysql_mutex_unlock(log_lock); + errmsg = "Could not read event_length"; + goto err; + } + next_event_len= uint4korr(buff); + cur_pos= cur_pos + next_event_len; + } + if (cur_pos > pos) + { + mysql_mutex_unlock(log_lock); + errmsg= "Invalid input pos specified please provide valid one."; + goto err; + } + my_b_seek(&log, cur_pos); + } + } for (event_count = 0; (ev = Log_event::read_log_event(&log, (mysql_mutex_t*) 0, diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 379a109c57c..19a9cdad184 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -12391,24 +12391,7 @@ void JOIN::cleanup(bool full) for (tab= first_linear_tab(this, WITH_BUSH_ROOTS, WITH_CONST_TABLES); tab; tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS)) { - if (!tab->table) - continue; - DBUG_PRINT("info", ("close index: %s.%s alias: %s", - tab->table->s->db.str, - tab->table->s->table_name.str, - tab->table->alias.c_ptr())); - if (tab->table->is_created()) - { - tab->table->file->ha_index_or_rnd_end(); - if (tab->aggr) - { - int tmp= 0; - if ((tmp= tab->table->file->extra(HA_EXTRA_NO_CACHE))) - tab->table->file->print_error(tmp, MYF(0)); - } - } - delete tab->filesort_result; - tab->filesort_result= NULL; + tab->partial_cleanup(); } } } @@ -21941,6 +21924,9 @@ check_reverse_order: else if (select && select->quick) select->quick->need_sorted_output(); + tab->read_record.unlock_row= (tab->type == JT_EQ_REF) ? + join_read_key_unlock_row : rr_unlock_row; + } // QEP has been modified /* @@ -26982,6 +26968,40 @@ void JOIN::handle_implicit_grouping_with_window_funcs() } } + +/* + @brief + Perform a partial cleanup for the JOIN_TAB structure + + @note + this is used to cleanup resources for the re-execution of correlated + subqueries. +*/ +void JOIN_TAB::partial_cleanup() +{ + if (!table) + return; + + if (table->is_created()) + { + table->file->ha_index_or_rnd_end(); + DBUG_PRINT("info", ("close index: %s.%s alias: %s", + table->s->db.str, + table->s->table_name.str, + table->alias.c_ptr())); + if (aggr) + { + int tmp= 0; + if ((tmp= table->file->extra(HA_EXTRA_NO_CACHE))) + table->file->print_error(tmp, MYF(0)); + } + } + delete filesort_result; + filesort_result= NULL; + free_cache(&read_record); +} + + /** @} (end of group Query_Optimizer) */ diff --git a/sql/sql_select.h b/sql/sql_select.h index 92da1355be0..4584460ca3f 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -613,7 +613,7 @@ typedef struct st_join_table { bool use_order() const; ///< Use ordering provided by chosen index? bool sort_table(); bool remove_duplicates(); - + void partial_cleanup(); } JOIN_TAB; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 18b7e92bca5..5544c765775 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -4430,7 +4430,7 @@ fill_schema_table_by_open(THD *thd, bool is_show_fields_or_keys, Again we don't do this for SHOW COLUMNS/KEYS because of backward compatibility. */ - if (!is_show_fields_or_keys && result && + if (!is_show_fields_or_keys && result && thd->is_error() && (thd->get_stmt_da()->sql_errno() == ER_NO_SUCH_TABLE || thd->get_stmt_da()->sql_errno() == ER_WRONG_OBJECT)) { @@ -5614,15 +5614,21 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, I.e. we are in SELECT FROM INFORMATION_SCHEMA.COLUMS rather than in SHOW COLUMNS */ - push_warning(thd, Sql_condition::WARN_LEVEL_WARN, - thd->get_stmt_da()->sql_errno(), - thd->get_stmt_da()->message()); - thd->clear_error(); + if (thd->is_error()) + { + /* + The the query was aborted because examined rows exceeded limit. + Don't send the warning here. It is done later, in handle_select(). + */ + push_warning(thd, Sql_condition::WARN_LEVEL_WARN, + thd->get_stmt_da()->sql_errno(), + thd->get_stmt_da()->message()); + thd->clear_error(); + } res= 0; } DBUG_RETURN(res); } - show_table= tables->table; count= 0; ptr= show_table->field; diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 177d2a77d09..b79ca82698b 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -826,7 +826,7 @@ int sortcmp(const String *s,const String *t, CHARSET_INFO *cs) int stringcmp(const String *s,const String *t) { uint32 s_len=s->length(),t_len=t->length(),len=MY_MIN(s_len,t_len); - int cmp= memcmp(s->ptr(), t->ptr(), len); + int cmp= len ? memcmp(s->ptr(), t->ptr(), len) : 0; return (cmp) ? cmp : (int) (s_len - t_len); } diff --git a/sql/sql_string.h b/sql/sql_string.h index 63404587404..512c5537840 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -555,7 +555,8 @@ public: } void q_append(const char *data, size_t data_len) { - memcpy(Ptr + str_length, data, data_len); + if (data_len) + memcpy(Ptr + str_length, data, data_len); DBUG_ASSERT(str_length <= UINT_MAX32 - data_len); str_length += (uint)data_len; } diff --git a/sql/sql_test.cc b/sql/sql_test.cc index db52ce0aea1..4e68ec2ec2e 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -387,10 +387,10 @@ void print_sjm(SJ_MATERIALIZATION_INFO *sjm) /* Debugging help: force List<...>::elem function not be removed as unused. */ -Item* (List<Item>:: *dbug_list_item_elem_ptr)(int)= &List<Item>::elem; -Item_equal* (List<Item_equal>:: *dbug_list_item_equal_elem_ptr)(int)= +Item* (List<Item>::*dbug_list_item_elem_ptr)(int)= &List<Item>::elem; +Item_equal* (List<Item_equal>::*dbug_list_item_equal_elem_ptr)(int)= &List<Item_equal>::elem; -TABLE_LIST* (List<TABLE_LIST>:: *dbug_list_table_list_elem_ptr)(int) = +TABLE_LIST* (List<TABLE_LIST>::*dbug_list_table_list_elem_ptr)(int) = &List<TABLE_LIST>::elem; #endif diff --git a/sql/sql_time.cc b/sql/sql_time.cc index 7f5919007e8..b92b35a3abb 100644 --- a/sql/sql_time.cc +++ b/sql/sql_time.cc @@ -358,7 +358,7 @@ static bool number_to_time_with_warn(bool neg, ulonglong nr, ulong sec_part, int was_cut; longlong res; enum_field_types f_type; - bool have_warnings; + bool have_warnings= false; if (fuzzydate & TIME_TIME_ONLY) { diff --git a/sql/sql_union.cc b/sql/sql_union.cc index b2198eb2b31..8b1719c60cb 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -514,6 +514,25 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, found_rows_for_union= first_sl->options & OPTION_FOUND_ROWS; is_union_select= is_union() || fake_select_lex; + /* + If we are reading UNION output and the UNION is in the + IN/ANY/ALL/EXISTS subquery, then ORDER BY is redundant and hence should + be removed. + Example: + select ... col IN (select col2 FROM t1 union select col3 from t2 ORDER BY 1) + + (as for ORDER BY ... LIMIT, it currently not supported inside + IN/ALL/ANY subqueries) + (For non-UNION this removal of ORDER BY clause is done in + check_and_do_in_subquery_rewrites()) + */ + if (is_union() && item && + (item->is_in_predicate() || item->is_exists_predicate())) + { + global_parameters()->order_list.first= NULL; + global_parameters()->order_list.elements= 0; + } + /* Global option */ if (is_union_select || is_recursive) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 386c86cb3e2..138d5e13701 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7692,6 +7692,8 @@ alter_list_item: | ALTER opt_column field_ident SET DEFAULT column_default_expr { LEX *lex=Lex; + if (check_expression($6, $3.str, VCOL_DEFAULT)) + MYSQL_YYABORT; Alter_column *ac= new (thd->mem_root) Alter_column($3.str,$6); if (ac == NULL) MYSQL_YYABORT; diff --git a/sql/sys_vars.ic b/sql/sys_vars.ic index a18440e550d..f547bd741fc 100644 --- a/sql/sys_vars.ic +++ b/sql/sys_vars.ic @@ -1704,13 +1704,16 @@ public: return false; } void session_save_default(THD *thd, set_var *var) - { var->save_result.ulonglong_value= global_var(ulonglong) & bitmask; } + { + var->save_result.ulonglong_value= + (reverse_semantics == !(global_var(ulonglong) & bitmask)); + } void global_save_default(THD *thd, set_var *var) { var->save_result.ulonglong_value= option.def_value; } uchar *valptr(THD *thd, ulonglong val) { - thd->sys_var_tmp.my_bool_value= reverse_semantics ^ ((val & bitmask) != 0); + thd->sys_var_tmp.my_bool_value= (reverse_semantics == !(val & bitmask)); return (uchar*) &thd->sys_var_tmp.my_bool_value; } uchar *session_value_ptr(THD *thd, const LEX_STRING *base) diff --git a/sql/table.h b/sql/table.h index f3a7f278604..14ab0027a79 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1281,9 +1281,16 @@ public: /* number of select if it is derived table */ uint derived_select_number; /* - 0 or JOIN_TYPE_{LEFT|RIGHT}. Currently this is only compared to 0. - If maybe_null !=0, this table is inner w.r.t. some outer join operation, - and null_row may be true. + Possible values: + - 0 by default + - JOIN_TYPE_{LEFT|RIGHT} if the table is inner w.r.t an outer join + operation + - 1 if the SELECT has mixed_implicit_grouping=1. example: + select max(col1), col2 from t1. In this case, the query produces + one row with all columns having NULL values. + + Interpetation: If maybe_null!=0, all fields of the table are considered + NULLable (and have NULL values when null_row=true) */ uint maybe_null; int current_lock; /* Type of lock on table */ diff --git a/sql/threadpool_common.cc b/sql/threadpool_common.cc index b0438770aae..fc9a79432f0 100644 --- a/sql/threadpool_common.cc +++ b/sql/threadpool_common.cc @@ -324,6 +324,16 @@ static void handle_wait_timeout(THD *thd) thd->net.error= 2; } +/** Check if some client data is cached in thd->net or thd->net.vio */ +static bool has_unread_data(THD* thd) +{ + NET *net= &thd->net; + if (net->compress && net->remain_in_buf) + return true; + Vio *vio= net->vio; + return vio->has_data(vio); +} + /** Process a single client request or a single batch. @@ -358,7 +368,6 @@ static int threadpool_process_request(THD *thd) */ for(;;) { - Vio *vio; thd->net.reading_or_writing= 0; if (mysql_audit_release_required(thd)) mysql_audit_release(thd); @@ -374,8 +383,7 @@ static int threadpool_process_request(THD *thd) set_thd_idle(thd); - vio= thd->net.vio; - if (!vio->has_data(vio)) + if (!has_unread_data(thd)) { /* More info on this debug sync is in sql_parse.cc*/ DEBUG_SYNC(thd, "before_do_command_net_read"); diff --git a/sql/threadpool_generic.cc b/sql/threadpool_generic.cc index 02eb336facb..78b57340a6b 100644 --- a/sql/threadpool_generic.cc +++ b/sql/threadpool_generic.cc @@ -1084,7 +1084,10 @@ void thread_group_destroy(thread_group_t *thread_group) #endif if (my_atomic_add32(&shutdown_group_count, -1) == 1) + { my_free(all_groups); + all_groups= 0; + } } /** @@ -1677,6 +1680,14 @@ TP_pool_generic::~TP_pool_generic() { thread_group_close(&all_groups[i]); } + + /* + Wait until memory occupied by all_groups is freed. + */ + int timeout_ms=5000; + while(all_groups && timeout_ms--) + my_sleep(1000); + threadpool_started= false; DBUG_VOID_RETURN; } diff --git a/sql/tztime.cc b/sql/tztime.cc index f58801bf4b7..067348dccab 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -2713,6 +2713,7 @@ main(int argc, char **argv) } if (opt_skip_write_binlog) + { /* If skip_write_binlog is set and wsrep is compiled in we disable sql_log_bin and wsrep_on to avoid Galera replicating below truncate table clauses. This will allow user to set different @@ -2720,15 +2721,9 @@ main(int argc, char **argv) printf("set @prep1=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on' and variable_value='ON'), 'SET SESSION SQL_LOG_BIN=?, WSREP_ON=OFF;', 'do ?');\n" "prepare set_wsrep_write_binlog from @prep1;\n" "set @toggle=0; execute set_wsrep_write_binlog using @toggle;\n"); - - if (argc == 1 && !opt_leap) + } + else { - /* Argument is timezonedir */ - - root_name_end= strmake_buf(fullname, argv[0]); - - if(!opt_skip_write_binlog) - { // Alter time zone tables to InnoDB if wsrep_on is enabled // to allow changes to them to replicate with Galera printf("\\d |\n" @@ -2740,15 +2735,23 @@ main(int argc, char **argv) "ALTER TABLE time_zone_transition_type ENGINE=InnoDB;\n" "END IF|\n" "\\d ;\n"); - } + } + + if (argc == 1 && !opt_leap) + { + /* Argument is timezonedir */ + + root_name_end= strmake_buf(fullname, argv[0]); printf("TRUNCATE TABLE time_zone;\n"); printf("TRUNCATE TABLE time_zone_name;\n"); printf("TRUNCATE TABLE time_zone_transition;\n"); printf("TRUNCATE TABLE time_zone_transition_type;\n"); + printf("START TRANSACTION;\n"); if (scan_tz_dir(root_name_end, 0, opt_verbose)) { + printf("ROLLBACK;\n"); fflush(stdout); fprintf(stderr, "There were fatal errors during processing " @@ -2756,6 +2759,7 @@ main(int argc, char **argv) return 1; } + printf("COMMIT;\n"); printf("ALTER TABLE time_zone_transition " "ORDER BY Time_zone_id, Transition_time;\n"); printf("ALTER TABLE time_zone_transition_type " diff --git a/sql/wsrep_dummy.cc b/sql/wsrep_dummy.cc index d8ab86c25f2..53941c06892 100644 --- a/sql/wsrep_dummy.cc +++ b/sql/wsrep_dummy.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2014 SkySQL Ab. +/* Copyright (C) 2014, 2020, MariaDB 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 @@ -154,3 +154,7 @@ void wsrep_log(void (*)(const char *, ...), const char *, ...) my_bool wsrep_thd_is_applier(MYSQL_THD thd) { return false; } + +void wsrep_report_bf_lock_wait(MYSQL_THD thd, + unsigned long long id) +{} diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index f95ef168a23..d392d1c2a61 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -2924,7 +2924,12 @@ static int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len) definer_host.length= 0; } - stmt_query.append(STRING_WITH_LEN("CREATE ")); + const LEX_STRING command[3]= + {{ C_STRING_WITH_LEN("CREATE ") }, + { C_STRING_WITH_LEN("ALTER ") }, + { C_STRING_WITH_LEN("CREATE OR REPLACE ") }}; + stmt_query.append(command[thd->lex->create_view_mode].str, + command[thd->lex->create_view_mode].length); append_definer(thd, &stmt_query, &definer_user, &definer_host); diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index e28b90885b4..3d68eda0d6b 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -131,8 +131,8 @@ extern const char* wsrep_provider_name; extern const char* wsrep_provider_version; extern const char* wsrep_provider_vendor; -int wsrep_show_status(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope); +int wsrep_show_status(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *status_var, enum_var_type scope); int wsrep_init(); void wsrep_deinit(bool free_options); diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index b62888ecbe1..65a3f971c62 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -1,4 +1,4 @@ -/* Copyright 2008-2015 Codership Oy <http://www.codership.com> +/* Copyright 2008-2020 Codership Oy <http://www.codership.com> 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 @@ -1542,10 +1542,13 @@ static void* sst_donor_thread (void* a) char out_buf[out_len]; wsrep_uuid_t ret_uuid= WSREP_UUID_UNDEFINED; - wsrep_seqno_t ret_seqno= WSREP_SEQNO_UNDEFINED; // seqno of complete SST + // seqno of complete SST + wsrep_seqno_t ret_seqno= WSREP_SEQNO_UNDEFINED; - wsp::thd thd(FALSE); // we turn off wsrep_on for this THD so that it can - // operate with wsrep_ready == OFF + // We turn off wsrep_on for this THD so that it can + // operate with wsrep_ready == OFF + // We also set this SST thread THD as system thread + wsp::thd thd(FALSE, true); wsp::process proc(arg->cmd, "r", arg->env); err= proc.error(); diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index 1e60088c5f1..4dddb399bd1 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -876,3 +876,23 @@ bool wsrep_is_load_multi_commit(THD *thd) { return thd->wsrep_split_flag; } + +void wsrep_report_bf_lock_wait(THD *thd, + unsigned long long trx_id) +{ + if (thd) + { + WSREP_ERROR("Thread %s trx_id: %llu thread: %ld " + "seqno: %lld query_state: %s conf_state: %s exec_mode: %s " + "applier: %d query: %s", + wsrep_thd_is_BF(thd, false) ? "BF" : "normal", + trx_id, + thd_get_thread_id(thd), + wsrep_thd_trx_seqno(thd), + wsrep_thd_query_state_str(thd), + wsrep_thd_conflict_state_str(thd), + wsrep_thd_exec_mode_str(thd), + thd->wsrep_applier, + wsrep_thd_query(thd)); + } +} diff --git a/sql/wsrep_thd.h b/sql/wsrep_thd.h index 10efcbefbf6..46bc08a466a 100644 --- a/sql/wsrep_thd.h +++ b/sql/wsrep_thd.h @@ -45,6 +45,9 @@ extern "C" my_bool wsrep_thd_is_BF_or_commit(void *thd_ptr, my_bool sync); extern "C" my_bool wsrep_thd_is_local(void *thd_ptr, my_bool sync); extern "C" int wsrep_thd_in_locking_session(void *thd_ptr); +extern void wsrep_report_bf_lock_wait(THD *thd, + unsigned long long trx_id); + #else /* WITH_WSREP */ #define wsrep_thd_is_BF(T, S) (0) diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc index 599ece4cb40..e86be3e5d93 100644 --- a/sql/wsrep_utils.cc +++ b/sql/wsrep_utils.cc @@ -413,7 +413,7 @@ process::wait () return err_; } -thd::thd (my_bool won) : init(), ptr(new THD(0)) +thd::thd (my_bool won, bool system_thread) : init(), ptr(new THD(0)) { if (ptr) { @@ -421,6 +421,8 @@ thd::thd (my_bool won) : init(), ptr(new THD(0)) ptr->store_globals(); ptr->variables.option_bits&= ~OPTION_BIN_LOG; // disable binlog ptr->variables.wsrep_on = won; + if (system_thread) + ptr->system_thread= SYSTEM_THREAD_GENERIC; ptr->security_ctx->master_access= ~(ulong)0; lex_start(ptr); } diff --git a/sql/wsrep_utils.h b/sql/wsrep_utils.h index 616a6d3f457..d4d9e62a620 100644 --- a/sql/wsrep_utils.h +++ b/sql/wsrep_utils.h @@ -298,7 +298,7 @@ class thd public: - thd(my_bool wsrep_on); + thd(my_bool wsrep_on, bool system_thread=false); ~thd(); THD* const ptr; }; diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 9777cc6ec62..45f929de9de 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -726,8 +726,8 @@ static int show_var_cmp(const void *var1, const void *var2) return strcasecmp(((SHOW_VAR*)var1)->name, ((SHOW_VAR*)var2)->name); } -int wsrep_show_status (THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +int wsrep_show_status (THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type scope) { uint i, maxi= SHOW_VAR_FUNC_BUFF_SIZE / sizeof(*var) - 1; SHOW_VAR *v= (SHOW_VAR *)buff; |