diff options
Diffstat (limited to 'sql')
40 files changed, 497 insertions, 239 deletions
diff --git a/sql/field.cc b/sql/field.cc index 76b917859d1..b5f4020af71 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -6643,25 +6643,33 @@ String *Field_string::val_str(String *val_buffer __attribute__((unused)), } -my_decimal *Field_string::val_decimal(my_decimal *decimal_value) +my_decimal *Field_longstr::val_decimal_from_str(const char *str, + uint length, + CHARSET_INFO *cs, + my_decimal *decimal_value) { - ASSERT_COLUMN_MARKED_FOR_READ; THD *thd; - int err= str2my_decimal(E_DEC_FATAL_ERROR, (char*) ptr, field_length, - charset(), decimal_value); + int err= str2my_decimal(E_DEC_FATAL_ERROR, str, length, cs, decimal_value); if (err && !(thd= get_thd())->no_errors) { - ErrConvString errmsg((char*) ptr, field_length, charset()); + ErrConvString errmsg(str, length, cs); push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_TRUNCATED_WRONG_VALUE, ER_THD(thd, ER_TRUNCATED_WRONG_VALUE), "DECIMAL", errmsg.ptr()); } - return decimal_value; } +my_decimal *Field_string::val_decimal(my_decimal *decimal_value) +{ + ASSERT_COLUMN_MARKED_FOR_READ; + return val_decimal_from_str((const char *) ptr, field_length, + Field_string::charset(), decimal_value); +} + + struct Check_field_param { Field *field; }; @@ -7078,18 +7086,9 @@ String *Field_varstring::val_str(String *val_buffer __attribute__((unused)), my_decimal *Field_varstring::val_decimal(my_decimal *decimal_value) { ASSERT_COLUMN_MARKED_FOR_READ; - CHARSET_INFO *cs= charset(); uint length= length_bytes == 1 ? (uint) *ptr : uint2korr(ptr); - int error= str2my_decimal(E_DEC_FATAL_ERROR, (char*) ptr+length_bytes, length, - cs, decimal_value); - - if (!get_thd()->no_errors && error) - { - push_numerical_conversion_warning(get_thd(), (char*)ptr+length_bytes, - length, cs, "DECIMAL", - ER_TRUNCATED_WRONG_VALUE); - } - return decimal_value; + return val_decimal_from_str((const char *) ptr + length_bytes, length, + Field_varstring::charset(), decimal_value); } @@ -7597,9 +7596,8 @@ my_decimal *Field_blob::val_decimal(my_decimal *decimal_value) else length= get_length(ptr); - str2my_decimal(E_DEC_FATAL_ERROR, blob, length, charset(), - decimal_value); - return decimal_value; + return val_decimal_from_str(blob, length, + Field_blob::charset(), decimal_value); } diff --git a/sql/field.h b/sql/field.h index 392041dcf67..ba44ee28cc6 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1227,6 +1227,9 @@ protected: const Item *item) const; bool cmp_to_string_with_stricter_collation(const Item_bool_func *cond, const Item *item) const; + my_decimal *val_decimal_from_str(const char *str, uint length, + CHARSET_INFO *cs, + my_decimal *decimal_value); public: Field_longstr(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, diff --git a/sql/gen_lex_token.cc b/sql/gen_lex_token.cc index 01a54b1b086..eefe9163819 100644 --- a/sql/gen_lex_token.cc +++ b/sql/gen_lex_token.cc @@ -56,6 +56,7 @@ int tok_row_single_value= 0; int tok_row_single_value_list= 0; int tok_row_multiple_value= 0; int tok_row_multiple_value_list= 0; +int tok_ident= 0; int tok_unused= 0; void set_token(int tok, const char *str) @@ -213,6 +214,10 @@ void compute_tokens() set_token(tok_row_multiple_value_list, "(...) /* , ... */"); max_token_seen++; + tok_ident= max_token_seen; + set_token(tok_ident, "(tok_id)"); + + max_token_seen++; tok_unused= max_token_seen; set_token(tok_unused, "UNUSED"); @@ -323,6 +328,7 @@ void print_tokens() printf("#define TOK_ROW_SINGLE_VALUE_LIST %d\n", tok_row_single_value_list); printf("#define TOK_ROW_MULTIPLE_VALUE %d\n", tok_row_multiple_value); printf("#define TOK_ROW_MULTIPLE_VALUE_LIST %d\n", tok_row_multiple_value_list); + printf("#define TOK_IDENT %d\n", tok_ident); printf("#define TOK_UNUSED %d\n", tok_unused); } diff --git a/sql/item.cc b/sql/item.cc index 0ec12678dee..823b8470f4a 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4320,18 +4320,23 @@ static bool mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current, Item_ident *resolved_item, Item_ident *mark_item) { - const char *db_name= (resolved_item->db_name ? - resolved_item->db_name : ""); - const char *table_name= (resolved_item->table_name ? - resolved_item->table_name : ""); + DBUG_ENTER("mark_as_dependent"); + /* store pointer on SELECT_LEX from which item is dependent */ if (mark_item && mark_item->can_be_depended) + { + DBUG_PRINT("info", ("mark_item: %p lex: %p", mark_item, last)); mark_item->depended_from= last; - if (current->mark_as_dependent(thd, last, /** resolved_item psergey-thu - **/mark_item)) - return TRUE; + } + if (current->mark_as_dependent(thd, last, + /** resolved_item psergey-thu **/ mark_item)) + DBUG_RETURN(TRUE); if (thd->lex->describe & DESCRIBE_EXTENDED) { + const char *db_name= (resolved_item->db_name ? + resolved_item->db_name : ""); + const char *table_name= (resolved_item->table_name ? + resolved_item->table_name : ""); push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, ER_WARN_FIELD_RESOLVED, ER_THD(thd,ER_WARN_FIELD_RESOLVED), @@ -4340,7 +4345,7 @@ static bool mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current, resolved_item->field_name, current->select_number, last->select_number); } - return FALSE; + DBUG_RETURN(FALSE); } @@ -4790,7 +4795,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) non aggregated fields of the outer select. */ marker= select->cur_pos_in_select_list; - select->non_agg_fields.push_back(this, thd->mem_root); + select->join->non_agg_fields.push_back(this, thd->mem_root); } if (*from_field != view_ref_found) { @@ -5209,9 +5214,10 @@ bool Item_field::fix_fields(THD *thd, Item **reference) fixed= 1; if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY && !outer_fixed && !thd->lex->in_sum_func && - thd->lex->current_select->cur_pos_in_select_list != UNDEF_POS) + thd->lex->current_select->cur_pos_in_select_list != UNDEF_POS && + thd->lex->current_select->join) { - thd->lex->current_select->non_agg_fields.push_back(this, thd->mem_root); + thd->lex->current_select->join->non_agg_fields.push_back(this, thd->mem_root); marker= thd->lex->current_select->cur_pos_in_select_list; } mark_non_agg_field: @@ -6787,7 +6793,7 @@ Item_ref::Item_ref(THD *thd, Name_resolution_context *context_arg, /* This constructor used to create some internals references over fixed items */ - if (ref && *ref && (*ref)->fixed) + if ((set_properties_only= (ref && *ref && (*ref)->fixed))) set_properties(); } @@ -6831,7 +6837,7 @@ Item_ref::Item_ref(THD *thd, TABLE_LIST *view_arg, Item **item, /* This constructor is used to create some internal references over fixed items */ - if (ref && *ref && (*ref)->fixed) + if ((set_properties_only= (ref && *ref && (*ref)->fixed))) set_properties(); } @@ -6906,7 +6912,11 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) DBUG_ASSERT(fixed == 0); SELECT_LEX *current_sel= thd->lex->current_select; - if (!ref || ref == not_found_item) + if (set_properties_only) + { + /* do nothing */ + } + else if (!ref || ref == not_found_item) { DBUG_ASSERT(reference_trough_name != 0); if (!(ref= resolve_ref_in_select_and_group(thd, this, @@ -7055,7 +7065,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) goto error; thd->change_item_tree(reference, fld); mark_as_dependent(thd, last_checked_context->select_lex, - thd->lex->current_select, fld, fld); + current_sel, fld, fld); /* A reference is resolved to a nest level that's outer or the same as the nest level of the enclosing set function : adjust the value of diff --git a/sql/item.h b/sql/item.h index 8faba4ddcb5..5b96e93dd1f 100644 --- a/sql/item.h +++ b/sql/item.h @@ -677,7 +677,7 @@ public: calls. */ uint name_length; /* Length of name */ - int8 marker; + int marker; bool maybe_null; /* If item may be null */ bool in_rollup; /* If used in GROUP BY list of a query with ROLLUP */ @@ -3599,6 +3599,7 @@ class Item_ref :public Item_ident { protected: void set_properties(); + bool set_properties_only; // the item doesn't need full fix_fields public: enum Ref_Type { REF, DIRECT_REF, VIEW_REF, OUTER_REF, AGGREGATE_REF }; Item **ref; @@ -3607,7 +3608,7 @@ public: const char *db_arg, const char *table_name_arg, const char *field_name_arg): Item_ident(thd, context_arg, db_arg, table_name_arg, field_name_arg), - ref(0), reference_trough_name(1) {} + set_properties_only(0), ref(0), reference_trough_name(1) {} /* This constructor is used in two scenarios: A) *item = NULL @@ -3630,7 +3631,7 @@ public: /* Constructor need to process subselect with temporary tables (see Item) */ Item_ref(THD *thd, Item_ref *item) - :Item_ident(thd, item), ref(item->ref) {} + :Item_ident(thd, item), set_properties_only(0), ref(item->ref) {} enum Type type() const { return REF_ITEM; } enum Type real_type() const { return ref ? (*ref)->type() : REF_ITEM; } diff --git a/sql/item_func.cc b/sql/item_func.cc index 79fed505d2d..5bb5f541694 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4280,6 +4280,21 @@ longlong Item_func_get_lock::val_int() DBUG_RETURN(1); } + if (args[1]->null_value || + (!args[1]->unsigned_flag && ((longlong) timeout < 0))) + { + char buf[22]; + if (args[1]->null_value) + strmov(buf, "NULL"); + else + llstr(((longlong) timeout), buf); + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_WRONG_VALUE_FOR_TYPE, ER(ER_WRONG_VALUE_FOR_TYPE), + "timeout", buf, "get_lock"); + null_value= 1; + DBUG_RETURN(0); + } + if (!ull_name_ok(res)) DBUG_RETURN(0); DBUG_PRINT("enter", ("lock: %.*s", res->length(), res->ptr())); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index a2ae5308e29..7d73393fdb2 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -478,6 +478,7 @@ void Item_subselect::recalc_used_tables(st_select_lex *new_parent, { List_iterator_fast<Ref_to_outside> it(upper_refs); Ref_to_outside *upper; + DBUG_ENTER("recalc_used_tables"); used_tables_cache= 0; while ((upper= it++)) @@ -537,6 +538,8 @@ void Item_subselect::recalc_used_tables(st_select_lex *new_parent, he has done const table detection, and that will be our chance to update const_tables_cache. */ + DBUG_PRINT("exit", ("used_tables_cache: %llx", used_tables_cache)); + DBUG_VOID_RETURN; } @@ -2022,7 +2025,7 @@ bool Item_allany_subselect::is_maxmin_applicable(JOIN *join) */ bool -Item_in_subselect::create_single_in_to_exists_cond(JOIN * join, +Item_in_subselect::create_single_in_to_exists_cond(JOIN *join, Item **where_item, Item **having_item) { @@ -2032,7 +2035,6 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN * join, during JOIN::optimize: this->tmp_having= this->having; this->having= 0; */ Item* join_having= join->having ? join->having : join->tmp_having; - DBUG_ENTER("Item_in_subselect::create_single_in_to_exists_cond"); *where_item= NULL; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index c56c4c217fb..ae21a94fc83 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -3536,9 +3536,17 @@ bool Item_func_group_concat::setup(THD *thd) "all_fields". The resulting field list is used as input to create tmp table columns. */ - if (arg_count_order && - setup_order(thd, args, context->table_list, list, all_fields, *order)) - DBUG_RETURN(TRUE); + if (arg_count_order) + { + uint n_elems= arg_count_order + all_fields.elements; + ref_pointer_array= static_cast<Item**>(thd->alloc(sizeof(Item*) * n_elems)); + if (!ref_pointer_array) + DBUG_RETURN(TRUE); + memcpy(ref_pointer_array, args, arg_count * sizeof(Item*)); + if (setup_order(thd, ref_pointer_array, context->table_list, list, + all_fields, *order)) + DBUG_RETURN(TRUE); + } count_field_types(select_lex, tmp_table_param, all_fields, 0); tmp_table_param->force_copy_fields= force_copy_fields; diff --git a/sql/item_sum.h b/sql/item_sum.h index b5613161d7c..01a580d03cb 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -1400,6 +1400,7 @@ class Item_func_group_concat : public Item_sum String *separator; TREE tree_base; TREE *tree; + Item **ref_pointer_array; /** If DISTINCT is used with this GROUP_CONCAT, this member is used to filter diff --git a/sql/log.cc b/sql/log.cc index f40ed4bcdc8..e3d9c3e98f8 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -4240,6 +4240,7 @@ int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included) int error; char *to_purge_if_included= NULL; inuse_relaylog *ir; + ulonglong log_space_reclaimed= 0; DBUG_ENTER("purge_first_log"); DBUG_ASSERT(is_open()); @@ -4311,17 +4312,13 @@ int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included) DBUG_EXECUTE_IF("crash_before_purge_logs", DBUG_SUICIDE();); - mysql_mutex_lock(&rli->log_space_lock); rli->relay_log.purge_logs(to_purge_if_included, included, - 0, 0, &rli->log_space_total); - mysql_mutex_unlock(&rli->log_space_lock); + 0, 0, &log_space_reclaimed); - /* - Ok to broadcast after the critical region as there is no risk of - the mutex being destroyed by this thread later - this helps save - context switches - */ + mysql_mutex_lock(&rli->log_space_lock); + rli->log_space_total-= log_space_reclaimed; mysql_cond_broadcast(&rli->log_space_cond); + mysql_mutex_unlock(&rli->log_space_lock); /* * Need to update the log pos because purge logs has been called @@ -4370,8 +4367,8 @@ int MYSQL_BIN_LOG::update_log_index(LOG_INFO* log_info, bool need_update_threads @param need_mutex @param need_update_threads If we want to update the log coordinates of all threads. False for relay logs, true otherwise. - @param freed_log_space If not null, decrement this variable of - the amount of log space freed + @param reclaimeed_log_space If not null, increment this variable to + the amount of log space freed @note If any of the logs before the deleted one is in use, @@ -4387,10 +4384,10 @@ int MYSQL_BIN_LOG::update_log_index(LOG_INFO* log_info, bool need_update_threads */ int MYSQL_BIN_LOG::purge_logs(const char *to_log, - bool included, - bool need_mutex, - bool need_update_threads, - ulonglong *decrease_log_space) + bool included, + bool need_mutex, + bool need_update_threads, + ulonglong *reclaimed_space) { int error= 0; bool exit_loop= 0; @@ -4454,7 +4451,7 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log, err: /* Read each entry from purge_index_file and delete the file. */ if (is_inited_purge_index_file() && - (error= purge_index_entry(thd, decrease_log_space, FALSE))) + (error= purge_index_entry(thd, reclaimed_space, FALSE))) sql_print_error("MSYQL_BIN_LOG::purge_logs failed to process registered files" " that would be purged."); close_purge_index_file(); @@ -4559,7 +4556,7 @@ int MYSQL_BIN_LOG::register_create_index_entry(const char *entry) DBUG_RETURN(register_purge_index_entry(entry)); } -int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *decrease_log_space, +int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *reclaimed_space, bool need_mutex) { DBUG_ENTER("MYSQL_BIN_LOG:purge_index_entry"); @@ -4672,8 +4669,8 @@ int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *decrease_log_space, DBUG_PRINT("info",("purging %s",log_info.log_file_name)); if (!my_delete(log_info.log_file_name, MYF(0))) { - if (decrease_log_space) - *decrease_log_space-= s.st_size; + if (reclaimed_space) + *reclaimed_space+= s.st_size; } else { @@ -6588,9 +6585,10 @@ int MYSQL_BIN_LOG::write_cache(THD *thd, IO_CACHE *cache) long val; ulong end_log_pos_inc= 0; // each event processed adds BINLOG_CHECKSUM_LEN 2 t uchar header[LOG_EVENT_HEADER_LEN]; - ha_checksum crc= 0, crc_0= 0; // assignments to keep compiler happy + ha_checksum crc= 0, crc_0= 0; my_bool do_checksum= (binlog_checksum_options != BINLOG_CHECKSUM_ALG_OFF); uchar buf[BINLOG_CHECKSUM_LEN]; + DBUG_ENTER("MYSQL_BIN_LOG::write_cache"); // while there is just one alg the following must hold: DBUG_ASSERT(!do_checksum || @@ -6612,9 +6610,7 @@ int MYSQL_BIN_LOG::write_cache(THD *thd, IO_CACHE *cache) group= (uint)my_b_tell(&log_file); hdr_offs= carry= 0; - if (do_checksum) - crc= crc_0= my_checksum(0L, NULL, 0); - + do { /* @@ -6643,7 +6639,7 @@ int MYSQL_BIN_LOG::write_cache(THD *thd, IO_CACHE *cache) /* write the first half of the split header */ if (my_b_write(&log_file, header, carry)) - return ER_ERROR_ON_WRITE; + DBUG_RETURN(ER_ERROR_ON_WRITE); status_var_add(thd->status_var.binlog_bytes_written, carry); /* @@ -6687,12 +6683,12 @@ int MYSQL_BIN_LOG::write_cache(THD *thd, IO_CACHE *cache) crc= my_checksum(crc, cache->read_pos, length); remains -= length; if (my_b_write(&log_file, cache->read_pos, length)) - return ER_ERROR_ON_WRITE; + DBUG_RETURN(ER_ERROR_ON_WRITE); if (remains == 0) { int4store(buf, crc); if (my_b_write(&log_file, buf, BINLOG_CHECKSUM_LEN)) - return ER_ERROR_ON_WRITE; + DBUG_RETURN(ER_ERROR_ON_WRITE); crc= crc_0; } } @@ -6719,7 +6715,7 @@ int MYSQL_BIN_LOG::write_cache(THD *thd, IO_CACHE *cache) DBUG_ASSERT(remains == 0); if (my_b_write(&log_file, cache->read_pos, hdr_offs) || my_b_write(&log_file, buf, BINLOG_CHECKSUM_LEN)) - return ER_ERROR_ON_WRITE; + DBUG_RETURN(ER_ERROR_ON_WRITE); crc= crc_0; } } @@ -6751,12 +6747,12 @@ int MYSQL_BIN_LOG::write_cache(THD *thd, IO_CACHE *cache) length, &crc); if (my_b_write(&log_file, ev, remains == 0 ? event_len : length - hdr_offs)) - return ER_ERROR_ON_WRITE; + DBUG_RETURN(ER_ERROR_ON_WRITE); if (remains == 0) { int4store(buf, crc); if (my_b_write(&log_file, buf, BINLOG_CHECKSUM_LEN)) - return ER_ERROR_ON_WRITE; + DBUG_RETURN(ER_ERROR_ON_WRITE); crc= crc_0; // crc is complete } } @@ -6781,10 +6777,10 @@ int MYSQL_BIN_LOG::write_cache(THD *thd, IO_CACHE *cache) /* Write data to the binary log file */ DBUG_EXECUTE_IF("fail_binlog_write_1", - errno= 28; return ER_ERROR_ON_WRITE;); + errno= 28; DBUG_RETURN(ER_ERROR_ON_WRITE);); if (!do_checksum) if (my_b_write(&log_file, cache->read_pos, length)) - return ER_ERROR_ON_WRITE; + DBUG_RETURN(ER_ERROR_ON_WRITE); status_var_add(thd->status_var.binlog_bytes_written, length); } while ((length= my_b_fill(cache))); @@ -6793,7 +6789,7 @@ int MYSQL_BIN_LOG::write_cache(THD *thd, IO_CACHE *cache) DBUG_ASSERT(!do_checksum || remains == 0); DBUG_ASSERT(!do_checksum || crc == crc_0); - return 0; // All OK + DBUG_RETURN(0); // All OK } /* diff --git a/sql/log_event.cc b/sql/log_event.cc index cb5b2c5cbbd..81c0d0c1304 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1089,12 +1089,22 @@ my_bool Log_event::need_checksum() and Stop event) provides their checksum alg preference through Log_event::checksum_alg. */ - ret= ((checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF) ? - (checksum_alg != BINLOG_CHECKSUM_ALG_OFF) : - ((binlog_checksum_options != BINLOG_CHECKSUM_ALG_OFF) && - (cache_type == Log_event::EVENT_NO_CACHE)) ? - MY_TEST(binlog_checksum_options) : FALSE); - + if (checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF) + ret= (checksum_alg != BINLOG_CHECKSUM_ALG_OFF); + else + { + if (binlog_checksum_options != BINLOG_CHECKSUM_ALG_OFF && + cache_type == Log_event::EVENT_NO_CACHE) + { + checksum_alg= binlog_checksum_options; + ret= MY_TEST(binlog_checksum_options); + } + else + { + ret= FALSE; + checksum_alg= (uint8) BINLOG_CHECKSUM_ALG_OFF; + } + } /* FD calls the methods before data_written has been calculated. The following invariant claims if the current is not the first @@ -1105,10 +1115,6 @@ my_bool Log_event::need_checksum() DBUG_ASSERT(get_type_code() != FORMAT_DESCRIPTION_EVENT || ret || data_written == 0); - if (checksum_alg == BINLOG_CHECKSUM_ALG_UNDEF) - checksum_alg= ret ? // calculated value stored - (uint8) binlog_checksum_options : (uint8) BINLOG_CHECKSUM_ALG_OFF; - DBUG_ASSERT(!ret || ((checksum_alg == binlog_checksum_options || /* @@ -1148,17 +1154,19 @@ bool Log_event::wrapper_my_b_safe_write(IO_CACHE* file, const uchar* buf, ulong bool Log_event::write_footer(IO_CACHE* file) { + DBUG_ENTER("write_footer"); /* footer contains the checksum-algorithm descriptor followed by the checksum value */ if (need_checksum()) { + DBUG_PRINT("info", ("Writing checksum")); uchar buf[BINLOG_CHECKSUM_LEN]; int4store(buf, crc); - return (my_b_safe_write(file, (uchar*) buf, sizeof(buf))); + DBUG_RETURN(my_b_safe_write(file, (uchar*) buf, sizeof(buf))); } - return 0; + DBUG_RETURN(0); } /* @@ -1180,7 +1188,7 @@ bool Log_event::write_header(IO_CACHE* file, ulong event_data_length) if (need_checksum()) { - crc= my_checksum(0L, NULL, 0); + crc= 0; data_written += BINLOG_CHECKSUM_LEN; } @@ -3072,6 +3080,7 @@ Query_log_event::Query_log_event() query_arg - array of char representing the query query_length - size of the `query_arg' array using_trans - there is a modified transactional table + direct - Don't cache statement suppress_use - suppress the generation of 'USE' statements errcode - the error code of the query @@ -3199,10 +3208,17 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, break; case SQLCOM_CREATE_TABLE: + /* + If we are using CREATE ... SELECT or if we are a slave + executing BEGIN...COMMIT (generated by CREATE...SELECT) we + have to use the transactional cache to ensure we don't + calculate any checksum for the CREATE part. + */ trx_cache= (lex->select_lex.item_list.elements && - thd->is_current_stmt_binlog_format_row()); + thd->is_current_stmt_binlog_format_row()) || + (thd->variables.option_bits & OPTION_GTID_BEGIN); use_cache= (lex->tmp_table() && - thd->in_multi_stmt_transaction_mode()) || trx_cache; + thd->in_multi_stmt_transaction_mode()) || trx_cache; break; case SQLCOM_SET_OPTION: if (lex->autocommit) @@ -3233,8 +3249,8 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, else cache_type= Log_event::EVENT_STMT_CACHE; DBUG_ASSERT(cache_type != Log_event::EVENT_INVALID_CACHE); - DBUG_PRINT("info",("Query_log_event has flags2: %lu sql_mode: %llu", - (ulong) flags2, sql_mode)); + DBUG_PRINT("info",("Query_log_event has flags2: %lu sql_mode: %llu cache_tye: %d", + (ulong) flags2, sql_mode, cache_type)); } #endif /* MYSQL_CLIENT */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f36d1cee9bc..76d74952e89 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5561,8 +5561,6 @@ int mysqld_main(int argc, char **argv) pfs_param.m_hints.m_table_open_cache= tc_size; pfs_param.m_hints.m_max_connections= max_connections; pfs_param.m_hints.m_open_files_limit= open_files_limit; - /* the performance schema digest size is the same as the SQL layer */ - pfs_param.m_max_digest_length= max_digest_length; PSI_hook= initialize_performance_schema(&pfs_param); if (PSI_hook == NULL) { diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index dac607195f0..9c6784437a7 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -4371,6 +4371,74 @@ int init_dups_weedout(JOIN *join, uint first_table, int first_fanout_table, uint /* + @brief + Set up semi-join Loose Scan strategy for execution + + @detail + Other strategies are done in setup_semijoin_dups_elimination(), + however, we need to set up Loose Scan earlier, before make_join_select is + called. This is to prevent make_join_select() from switching full index + scans into quick selects (which will break Loose Scan access). + + @return + 0 OK + 1 Error +*/ + +int setup_semijoin_loosescan(JOIN *join) +{ + uint i; + DBUG_ENTER("setup_semijoin_loosescan"); + + POSITION *pos= join->best_positions + join->const_tables; + for (i= join->const_tables ; i < join->top_join_tab_count; ) + { + JOIN_TAB *tab=join->join_tab + i; + switch (pos->sj_strategy) { + case SJ_OPT_MATERIALIZE: + case SJ_OPT_MATERIALIZE_SCAN: + i+= 1; /* join tabs are embedded in the nest */ + pos += pos->n_sj_tables; + break; + case SJ_OPT_LOOSE_SCAN: + { + /* We jump from the last table to the first one */ + tab->loosescan_match_tab= tab + pos->n_sj_tables - 1; + + /* LooseScan requires records to be produced in order */ + if (tab->select && tab->select->quick) + tab->select->quick->need_sorted_output(); + + for (uint j= i; j < i + pos->n_sj_tables; j++) + join->join_tab[j].inside_loosescan_range= TRUE; + + /* Calculate key length */ + uint keylen= 0; + uint keyno= pos->loosescan_picker.loosescan_key; + for (uint kp=0; kp < pos->loosescan_picker.loosescan_parts; kp++) + keylen += tab->table->key_info[keyno].key_part[kp].store_length; + + tab->loosescan_key= keyno; + tab->loosescan_key_len= keylen; + if (pos->n_sj_tables > 1) + tab[pos->n_sj_tables - 1].do_firstmatch= tab; + i+= pos->n_sj_tables; + pos+= pos->n_sj_tables; + break; + } + default: + { + i++; + pos++; + break; + } + } + } + DBUG_RETURN(FALSE); +} + + +/* Setup the strategies to eliminate semi-join duplicates. SYNOPSIS @@ -4478,8 +4546,6 @@ int setup_semijoin_dups_elimination(JOIN *join, ulonglong options, for (i= join->const_tables ; i < join->top_join_tab_count; ) { JOIN_TAB *tab=join->join_tab + i; - //POSITION *pos= join->best_positions + i; - uint keylen, keyno; switch (pos->sj_strategy) { case SJ_OPT_MATERIALIZE: case SJ_OPT_MATERIALIZE_SCAN: @@ -4489,26 +4555,7 @@ int setup_semijoin_dups_elimination(JOIN *join, ulonglong options, break; case SJ_OPT_LOOSE_SCAN: { - /* We jump from the last table to the first one */ - tab->loosescan_match_tab= tab + pos->n_sj_tables - 1; - - /* LooseScan requires records to be produced in order */ - if (tab->select && tab->select->quick) - tab->select->quick->need_sorted_output(); - - for (uint j= i; j < i + pos->n_sj_tables; j++) - join->join_tab[j].inside_loosescan_range= TRUE; - - /* Calculate key length */ - keylen= 0; - keyno= pos->loosescan_picker.loosescan_key; - for (uint kp=0; kp < pos->loosescan_picker.loosescan_parts; kp++) - keylen += tab->table->key_info[keyno].key_part[kp].store_length; - - tab->loosescan_key= keyno; - tab->loosescan_key_len= keylen; - if (pos->n_sj_tables > 1) - tab[pos->n_sj_tables - 1].do_firstmatch= tab; + /* Setup already handled by setup_semijoin_loosescan */ i+= pos->n_sj_tables; pos+= pos->n_sj_tables; break; diff --git a/sql/opt_subselect.h b/sql/opt_subselect.h index a2f6b644bf2..8daa973f825 100644 --- a/sql/opt_subselect.h +++ b/sql/opt_subselect.h @@ -195,8 +195,6 @@ public: PREV_BITS(key_part_map, max_loose_keypart+1) && // (3) !key_uses_partial_cols(s->table->s, key)) { - /* Ok, can use the strategy */ - part1_conds_met= TRUE; if (s->quick && s->quick->index == key && s->quick->get_type() == QUICK_SELECT_I::QS_TYPE_RANGE) { @@ -205,6 +203,12 @@ public: } DBUG_PRINT("info", ("Can use LooseScan scan")); + if (found_part & 1) + { + /* Can use LooseScan on ref access if the first key part is bound */ + part1_conds_met= TRUE; + } + /* Check if this is a special case where there are no usable bound IN-equalities, i.e. we have @@ -212,11 +216,13 @@ public: outer_expr IN (SELECT innertbl.key FROM ...) and outer_expr cannot be evaluated yet, so it's actually full - index scan and not a ref access + index scan and not a ref access. + We can do full index scan if it uses index-only. */ if (!(found_part & 1 ) && /* no usable ref access for 1st key part */ s->table->covering_keys.is_set(key)) { + part1_conds_met= TRUE; DBUG_PRINT("info", ("Can use full index scan for LooseScan")); /* Calculate the cost of complete loose index scan. */ @@ -384,6 +390,7 @@ public: bool create_sj_weedout_tmp_table(THD *thd); }; +int setup_semijoin_loosescan(JOIN *join); int setup_semijoin_dups_elimination(JOIN *join, ulonglong options, uint no_jbuf_after); void destroy_sj_tmp_tables(JOIN *join); diff --git a/sql/rpl_handler.cc b/sql/rpl_handler.cc index 3962600f600..733af6c61c8 100644 --- a/sql/rpl_handler.cc +++ b/sql/rpl_handler.cc @@ -39,8 +39,6 @@ typedef struct Trans_binlog_info { char log_file[FN_REFLEN]; } Trans_binlog_info; -static pthread_key(Trans_binlog_info*, RPL_TRANS_BINLOG_INFO); - int get_user_var_int(const char *name, long long int *value, int *null_value) { @@ -144,13 +142,6 @@ int delegates_init() } #endif - if (pthread_key_create(&RPL_TRANS_BINLOG_INFO, NULL)) - { - sql_print_error("Error while creating pthread specific data key for replication. " - "Please report a bug."); - return 1; - } - return 0; } @@ -196,27 +187,27 @@ void delegates_destroy() int Trans_delegate::after_commit(THD *thd, bool all) { Trans_param param; + Trans_binlog_info *log_info; bool is_real_trans= (all || thd->transaction.all.ha_list == 0); + int ret= 0; param.flags = is_real_trans ? TRANS_IS_REAL_TRANS : 0; - Trans_binlog_info *log_info= - my_pthread_getspecific_ptr(Trans_binlog_info*, RPL_TRANS_BINLOG_INFO); + log_info= thd->semisync_info; - param.log_file= log_info ? log_info->log_file : 0; + param.log_file= log_info && log_info->log_file[0] ? log_info->log_file : 0; param.log_pos= log_info ? log_info->log_pos : 0; - int ret= 0; FOREACH_OBSERVER(ret, after_commit, false, (¶m)); /* This is the end of a real transaction or autocommit statement, we - can free the memory allocated for binlog file and position. + can mark the memory unused. */ if (is_real_trans && log_info) { - my_pthread_setspecific_ptr(RPL_TRANS_BINLOG_INFO, NULL); - my_free(log_info); + log_info->log_file[0]= 0; + log_info->log_pos= 0; } return ret; } @@ -224,27 +215,27 @@ int Trans_delegate::after_commit(THD *thd, bool all) int Trans_delegate::after_rollback(THD *thd, bool all) { Trans_param param; + Trans_binlog_info *log_info; bool is_real_trans= (all || thd->transaction.all.ha_list == 0); + int ret= 0; param.flags = is_real_trans ? TRANS_IS_REAL_TRANS : 0; - Trans_binlog_info *log_info= - my_pthread_getspecific_ptr(Trans_binlog_info*, RPL_TRANS_BINLOG_INFO); - - param.log_file= log_info ? log_info->log_file : 0; + log_info= thd->semisync_info; + + param.log_file= log_info && log_info->log_file[0] ? log_info->log_file : 0; param.log_pos= log_info ? log_info->log_pos : 0; - int ret= 0; FOREACH_OBSERVER(ret, after_rollback, false, (¶m)); /* This is the end of a real transaction or autocommit statement, we - can free the memory allocated for binlog file and position. + can mark the memory unused. */ if (is_real_trans && log_info) { - my_pthread_setspecific_ptr(RPL_TRANS_BINLOG_INFO, NULL); - my_free(log_info); + log_info->log_file[0]= 0; + log_info->log_pos= 0; } return ret; } @@ -257,7 +248,10 @@ int Binlog_storage_delegate::after_flush(THD *thd, bool last_in_group) { Binlog_storage_param param; + Trans_binlog_info *log_info; uint32 flags=0; + int ret= 0; + if (synced) flags |= BINLOG_STORAGE_IS_SYNCED; if (first_in_group) @@ -265,21 +259,17 @@ int Binlog_storage_delegate::after_flush(THD *thd, if (last_in_group) flags|= BINLOG_GROUP_COMMIT_TRAILER; - Trans_binlog_info *log_info= - my_pthread_getspecific_ptr(Trans_binlog_info*, RPL_TRANS_BINLOG_INFO); - - if (!log_info) + if (!(log_info= thd->semisync_info)) { if(!(log_info= - (Trans_binlog_info *)my_malloc(sizeof(Trans_binlog_info), MYF(0)))) + (Trans_binlog_info*) my_malloc(sizeof(Trans_binlog_info), MYF(0)))) return 1; - my_pthread_setspecific_ptr(RPL_TRANS_BINLOG_INFO, log_info); + thd->semisync_info= log_info; } - + strcpy(log_info->log_file, log_file+dirname_length(log_file)); log_info->log_pos = log_pos; - int ret= 0; FOREACH_OBSERVER(ret, after_flush, false, (¶m, log_info->log_file, log_info->log_pos, flags)); return ret; diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc index dadd9de748c..5147dc4f0cb 100644 --- a/sql/rpl_utility.cc +++ b/sql/rpl_utility.cc @@ -950,6 +950,7 @@ TABLE *table_def::create_conversion_table(THD *thd, rpl_group_info *rgi, { Create_field *field_def= (Create_field*) alloc_root(thd->mem_root, sizeof(Create_field)); + bool unsigned_flag= 0; if (field_list.push_back(field_def, thd->mem_root)) DBUG_RETURN(NULL); @@ -959,8 +960,7 @@ TABLE *table_def::create_conversion_table(THD *thd, rpl_group_info *rgi, uint32 max_length= max_display_length_for_field(type(col), field_metadata(col)); - switch(type(col)) - { + switch(type(col)) { int precision; case MYSQL_TYPE_ENUM: case MYSQL_TYPE_SET: @@ -999,6 +999,18 @@ TABLE *table_def::create_conversion_table(THD *thd, rpl_group_info *rgi, pack_length= field_metadata(col) & 0x00ff; break; + case MYSQL_TYPE_TINY: + case MYSQL_TYPE_SHORT: + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_LONGLONG: + /* + As we don't know if the integer was signed or not on the master, + assume we have same sign on master and slave. This is true when not + using conversions so it should be true also when using conversions. + */ + unsigned_flag= ((Field_num*) target_table->field[col])->unsigned_flag; + break; default: break; } @@ -1006,12 +1018,13 @@ TABLE *table_def::create_conversion_table(THD *thd, rpl_group_info *rgi, DBUG_PRINT("debug", ("sql_type: %d, target_field: '%s', max_length: %d, decimals: %d," " maybe_null: %d, unsigned_flag: %d, pack_length: %u", binlog_type(col), target_table->field[col]->field_name, - max_length, decimals, TRUE, FALSE, pack_length)); + max_length, decimals, TRUE, unsigned_flag, + pack_length)); field_def->init_for_tmp_table(type(col), max_length, decimals, TRUE, // maybe_null - FALSE, // unsigned_flag + unsigned_flag, pack_length); field_def->charset= target_table->field[col]->charset(); field_def->interval= interval; @@ -1179,7 +1192,7 @@ bool event_checksum_test(uchar *event_buf, ulong event_len, uint8 alg) compile_time_assert(BINLOG_CHECKSUM_ALG_ENUM_END <= 0x80); } incoming= uint4korr(event_buf + event_len - BINLOG_CHECKSUM_LEN); - computed= my_checksum(0L, NULL, 0); + computed= 0; /* checksum the event content but the checksum part itself */ computed= my_checksum(computed, (const uchar*) event_buf, event_len - BINLOG_CHECKSUM_LEN); @@ -1257,4 +1270,3 @@ void Deferred_log_events::rewind() } #endif - diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 0f519fdd33b..59908dc51c0 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -7109,6 +7109,9 @@ ER_SLAVE_SKIP_NOT_IN_GTID eng "When using GTID, @@sql_slave_skip_counter can not be used. Instead, setting @@gtid_slave_pos explicitly can be used to skip to after a given GTID position." ER_TABLE_DEFINITION_TOO_BIG eng "The definition for table %`s is too big" +ER_PLUGIN_INSTALLED + eng "Plugin '%-.192s' already installed" + rus "Плагин '%-.192s' уже установлен" ER_STATEMENT_TIMEOUT 70100 eng "Query execution was interrupted (max_statement_time exceeded)" ER_SUBQUERIES_NOT_SUPPORTED 42000 diff --git a/sql/slave.cc b/sql/slave.cc index 3bbc7610649..659f3a90574 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -4619,9 +4619,7 @@ pthread_handler_t handle_slave_sql(void *arg) rli->parallel.reset(); //tell the I/O thread to take relay_log_space_limit into account from now on - mysql_mutex_lock(&rli->log_space_lock); rli->ignore_log_space_limit= 0; - mysql_mutex_unlock(&rli->log_space_lock); serial_rgi->gtid_sub_id= 0; serial_rgi->gtid_pending= false; @@ -5594,7 +5592,7 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) if (uint4korr(&buf[0]) == 0 && checksum_alg == BINLOG_CHECKSUM_ALG_OFF && mi->rli.relay_log.relay_log_checksum_alg != BINLOG_CHECKSUM_ALG_OFF) { - ha_checksum rot_crc= my_checksum(0L, NULL, 0); + ha_checksum rot_crc= 0; event_len += BINLOG_CHECKSUM_LEN; memcpy(rot_buf, buf, event_len - BINLOG_CHECKSUM_LEN); int4store(&rot_buf[EVENT_LEN_OFFSET], @@ -6819,14 +6817,8 @@ static Log_event* next_event(rpl_group_info *rgi, ulonglong *event_size) rli->ignore_log_space_limit= true; } - /* - If the I/O thread is blocked, unblock it. Ok to broadcast - after unlock, because the mutex is only destroyed in - ~Relay_log_info(), i.e. when rli is destroyed, and rli will - not be destroyed before we exit the present function. - */ - mysql_mutex_unlock(&rli->log_space_lock); mysql_cond_broadcast(&rli->log_space_cond); + mysql_mutex_unlock(&rli->log_space_lock); // Note that wait_for_update_relay_log unlocks lock_log ! rli->relay_log.wait_for_update_relay_log(rli->sql_driver_thd); // re-acquire data lock since we released it earlier diff --git a/sql/sp.cc b/sql/sp.cc index 46970bafdfc..6ec59143720 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1797,7 +1797,8 @@ sp_find_routine(THD *thd, stored_procedure_type type, sp_name *name, @param thd Thread handler @param routines List of needles in the hay stack - @param any Any of the needles are good enough + @param is_proc Indicates whether routines in the list are procedures + or functions. @return @retval FALSE Found. @@ -1805,7 +1806,7 @@ sp_find_routine(THD *thd, stored_procedure_type type, sp_name *name, */ bool -sp_exist_routines(THD *thd, TABLE_LIST *routines, bool any) +sp_exist_routines(THD *thd, TABLE_LIST *routines, bool is_proc) { TABLE_LIST *routine; bool sp_object_found; @@ -1821,17 +1822,14 @@ sp_exist_routines(THD *thd, TABLE_LIST *routines, bool any) lex_name.str= thd->strmake(routine->table_name, lex_name.length); name= new sp_name(lex_db, lex_name, true); name->init_qname(thd); - sp_object_found= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, name, - &thd->sp_proc_cache, FALSE) != NULL || - sp_find_routine(thd, TYPE_ENUM_FUNCTION, name, - &thd->sp_func_cache, FALSE) != NULL; + sp_object_found= is_proc ? sp_find_routine(thd, TYPE_ENUM_PROCEDURE, + name, &thd->sp_proc_cache, + FALSE) != NULL : + sp_find_routine(thd, TYPE_ENUM_FUNCTION, + name, &thd->sp_func_cache, + FALSE) != NULL; thd->get_stmt_da()->clear_warning_info(thd->query_id); - if (sp_object_found) - { - if (any) - break; - } - else if (!any) + if (! sp_object_found) { my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION or PROCEDURE", routine->table_name); @@ -121,7 +121,7 @@ sp_cache_routine(THD *thd, stored_procedure_type type, sp_name *name, bool lookup_only, sp_head **sp); bool -sp_exist_routines(THD *thd, TABLE_LIST *procs, bool any); +sp_exist_routines(THD *thd, TABLE_LIST *procs, bool is_proc); bool sp_show_create_routine(THD *thd, stored_procedure_type type, sp_name *name); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index a97827bae88..86b37742bea 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3439,10 +3439,11 @@ request_backoff_action(enum_open_table_action action_arg, * We met a broken table that needs repair, or a table that is not present on this MySQL server and needs re-discovery. To perform the action, we need an exclusive metadata lock on - the table. Acquiring an X lock while holding other shared - locks is very deadlock-prone. If this is a multi- statement - transaction that holds metadata locks for completed - statements, we don't do it, and report an error instead. + the table. Acquiring X lock while holding other shared + locks can easily lead to deadlocks. We rely on MDL deadlock + detector to discover them. If this is a multi-statement + transaction that holds metadata locks for completed statements, + we should keep these locks after discovery/repair. The action type in this case is OT_DISCOVER or OT_REPAIR. * Our attempt to acquire an MDL lock lead to a deadlock, detected by the MDL deadlock detector. The current @@ -3483,7 +3484,7 @@ request_backoff_action(enum_open_table_action action_arg, keep tables open between statements and a livelock is not possible. */ - if (action_arg != OT_REOPEN_TABLES && m_has_locks) + if (action_arg == OT_BACKOFF_AND_RETRY && m_has_locks) { my_error(ER_LOCK_DEADLOCK, MYF(0)); m_thd->mark_transaction_to_rollback(true); @@ -3512,6 +3513,32 @@ request_backoff_action(enum_open_table_action action_arg, /** + An error handler to mark transaction to rollback on DEADLOCK error + during DISCOVER / REPAIR. +*/ +class MDL_deadlock_discovery_repair_handler : public Internal_error_handler +{ +public: + virtual bool handle_condition(THD *thd, + uint sql_errno, + const char* sqlstate, + Sql_condition::enum_warning_level level, + const char* msg, + Sql_condition ** cond_hdl) + { + if (sql_errno == ER_LOCK_DEADLOCK) + { + thd->mark_transaction_to_rollback(true); + } + /* + We have marked this transaction to rollback. Return false to allow + error to be reported or handled by other handlers. + */ + return false; + } +}; + +/** Recover from failed attempt of open table by performing requested action. @pre This function should be called only with "action" != OT_NO_ACTION @@ -3525,6 +3552,12 @@ bool Open_table_context::recover_from_failed_open() { bool result= FALSE; + MDL_deadlock_discovery_repair_handler handler; + /* + Install error handler to mark transaction to rollback on DEADLOCK error. + */ + m_thd->push_internal_handler(&handler); + /* Execute the action. */ switch (m_action) { @@ -3561,7 +3594,12 @@ Open_table_context::recover_from_failed_open() result= FALSE; } - m_thd->mdl_context.release_transactional_locks(); + /* + Rollback to start of the current statement to release exclusive lock + on table which was discovered but preserve locks from previous statements + in current transaction. + */ + m_thd->mdl_context.rollback_to_savepoint(start_of_statement_svp()); break; } case OT_REPAIR: @@ -3575,12 +3613,18 @@ Open_table_context::recover_from_failed_open() m_failed_table->table_name, FALSE); result= auto_repair_table(m_thd, m_failed_table); - m_thd->mdl_context.release_transactional_locks(); + /* + Rollback to start of the current statement to release exclusive lock + on table which was discovered but preserve locks from previous statements + in current transaction. + */ + m_thd->mdl_context.rollback_to_savepoint(start_of_statement_svp()); break; } default: DBUG_ASSERT(0); } + m_thd->pop_internal_handler(); /* Reset the pointers to conflicting MDL request and the TABLE_LIST element, set when we need auto-discovery or repair, @@ -6611,6 +6655,7 @@ find_field_in_tables(THD *thd, Item_ident *item, if (item->cached_table) { + DBUG_PRINT("info", ("using cached table")); /* This shortcut is used by prepared statements. We assume that TABLE_LIST *first_table is not changed during query execution (which @@ -7363,14 +7408,6 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2, */ result= FALSE; - /* - Save the lists made during natural join matching (because - the matching done only once but we need the list in case - of prepared statements). - */ - table_ref_1->persistent_used_items= table_ref_1->used_items; - table_ref_2->persistent_used_items= table_ref_2->used_items; - err: if (arena) thd->restore_active_arena(arena, &backup); @@ -8418,11 +8455,6 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, } } #endif - /* - field_iterator.create_item() builds used_items which we - have to save because changes made once and they are persistent - */ - tables->persistent_used_items= tables->used_items; if ((field= field_iterator.field())) { diff --git a/sql/sql_class.cc b/sql/sql_class.cc index a367e0b44df..9b225de1ab8 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -961,6 +961,7 @@ THD::THD(bool is_wsrep_applier) file_id = 0; query_id= 0; query_name_consts= 0; + semisync_info= 0; db_charset= global_system_variables.collation_database; bzero(ha_data, sizeof(ha_data)); mysys_var=0; @@ -1418,6 +1419,7 @@ void THD::init(void) bzero((char *) &org_status_var, sizeof(org_status_var)); start_bytes_received= 0; last_commit_gtid.seq_no= 0; + status_in_global= 0; #ifdef WITH_WSREP wsrep_exec_mode= wsrep_applier ? REPL_RECV : LOCAL_STATE; wsrep_conflict_state= NO_CONFLICT; @@ -1540,6 +1542,7 @@ void THD::change_user(void) cleanup(); reset_killed(); cleanup_done= 0; + status_in_global= 0; init(); stmt_map.reset(); my_hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0, @@ -1676,6 +1679,7 @@ THD::~THD() mysql_audit_free_thd(this); if (rgi_slave) rgi_slave->cleanup_after_session(); + my_free(semisync_info); #endif main_lex.free_set_stmt_mem_root(); free_root(&main_mem_root, MYF(0)); diff --git a/sql/sql_class.h b/sql/sql_class.h index 645862f8183..d9a0913d972 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -66,7 +66,6 @@ class Reprepare_observer; class Relay_log_info; struct rpl_group_info; class Rpl_filter; - class Query_log_event; class Load_log_event; class Slave_log_event; @@ -77,6 +76,7 @@ class Parser_state; class Rows_log_event; class Sroutine_hash_entry; class user_var_entry; +struct Trans_binlog_info; class rpl_io_thread_info; class rpl_sql_thread_info; @@ -2043,6 +2043,9 @@ public: */ const char *where; + /* Needed by MariaDB semi sync replication */ + Trans_binlog_info *semisync_info; + ulong client_capabilities; /* What the client supports */ ulong max_client_packet_length; @@ -2111,11 +2114,11 @@ public: /* Do not set socket timeouts for wait_timeout (used with threadpool) */ bool skip_wait_timeout; - /* container for handler's private per-connection data */ - Ha_data ha_data[MAX_HA]; - bool prepare_derived_at_open; + /* Set to 1 if status of this THD is already in global status */ + bool status_in_global; + /* To signal that the tmp table to be created is created for materialized derived table or a view. @@ -2124,6 +2127,9 @@ public: bool save_prep_leaf_list; + /* container for handler's private per-connection data */ + Ha_data ha_data[MAX_HA]; + #ifndef MYSQL_CLIENT binlog_cache_mngr * binlog_setup_trx_data(); @@ -3833,6 +3839,8 @@ public: { mysql_mutex_lock(&LOCK_status); add_to_status(&global_status_var, &status_var); + /* Mark that this THD status has already been added in global status */ + status_in_global= 1; mysql_mutex_unlock(&LOCK_status); } diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc index 27dea480025..a8c5569ba4a 100644 --- a/sql/sql_cursor.cc +++ b/sql/sql_cursor.cc @@ -54,6 +54,8 @@ public: virtual void fetch(ulong num_rows); virtual void close(); virtual ~Materialized_cursor(); + + void on_table_fill_finished(); }; @@ -74,6 +76,18 @@ public: Select_materialize(THD *thd_arg, select_result *result_arg): select_union(thd_arg), result(result_arg), materialized_cursor(0) {} virtual bool send_result_set_metadata(List<Item> &list, uint flags); + bool send_eof() + { + if (materialized_cursor) + materialized_cursor->on_table_fill_finished(); + return false; + } + + void abort_result_set() + { + if (materialized_cursor) + materialized_cursor->on_table_fill_finished(); + } }; @@ -389,6 +403,29 @@ Materialized_cursor::~Materialized_cursor() } +/* + @brief + Perform actions that are to be done when cursor materialization has + finished. + + @detail + This function is called when "OPEN $cursor" has finished filling the + temporary table with rows that the cursor will return. + + Temporary table has table->field->orig_table pointing at the tables + that are used in the cursor definition query. Pointers to these tables + will not be valid after the query finishes. So, we do what is done for + regular tables: have orig_table point at the table that the fields belong + to. +*/ + +void Materialized_cursor::on_table_fill_finished() +{ + uint fields= table->s->fields; + for (uint i= 0; i < fields; i++) + table->field[i]->orig_table= table->field[i]->table; +} + /*************************************************************************** Select_materialize ****************************************************************************/ diff --git a/sql/sql_digest.cc b/sql/sql_digest.cc index cdbfcbb2e89..7f6f3bbfe9b 100644 --- a/sql/sql_digest.cc +++ b/sql/sql_digest.cc @@ -224,6 +224,7 @@ void compute_digest_text(const sql_digest_storage* digest_storage, /* All identifiers are printed with their name. */ case IDENT: case IDENT_QUOTED: + case TOK_IDENT: { char *id_ptr= NULL; int id_len= 0; @@ -259,13 +260,10 @@ void compute_digest_text(const sql_digest_storage* digest_storage, break; } /* Copy the converted identifier into the digest string. */ - if (tok == IDENT_QUOTED) - digest_output->append("`", 1); + digest_output->append("`", 1); if (id_length > 0) digest_output->append(id_string, id_length); - if (tok == IDENT_QUOTED) - digest_output->append("`", 1); - digest_output->append(" ", 1); + digest_output->append("` ", 2); } break; @@ -575,6 +573,15 @@ sql_digest_state* digest_add_token(sql_digest_state *state, char *yytext= lex_token->lex_str.str; size_t yylen= lex_token->lex_str.length; + /* + REDUCE: + TOK_IDENT := IDENT | IDENT_QUOTED + The parser gives IDENT or IDENT_TOKEN for the same text, + depending on the character set used. + We unify both to always print the same digest text, + and always have the same digest hash. + */ + token= TOK_IDENT; /* Add this token and identifier string to digest storage. */ store_token_identifier(digest_storage, token, yylen, yytext); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 0dce2f4c0ae..12f55acf5a0 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1934,7 +1934,6 @@ void st_select_lex::init_select() with_sum_func= 0; is_correlated= 0; cur_pos_in_select_list= UNDEF_POS; - non_agg_fields.empty(); cond_value= having_value= Item::COND_UNDEF; inner_refs_list.empty(); insert_tables= 0; @@ -1942,6 +1941,7 @@ void st_select_lex::init_select() m_non_agg_field_used= false; m_agg_func_used= false; name_visibility_map= 0; + join= 0; } /* diff --git a/sql/sql_lex.h b/sql/sql_lex.h index da44cb31523..473fd18a2ee 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -870,8 +870,6 @@ public: bool no_wrap_view_item; /* exclude this select from check of unique_table() */ bool exclude_from_table_unique_test; - /* List of fields that aren't under an aggregate function */ - List<Item_field> non_agg_fields; /* index in the select list of the expression currently being fixed */ int cur_pos_in_select_list; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 7d64f263a4a..2870e90ef4d 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -299,6 +299,18 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, table->prepare_triggers_for_insert_stmt_or_event(); table->mark_columns_needed_for_insert(); + if (table->vfield) + { + for (Field **vfield_ptr= table->vfield; *vfield_ptr; vfield_ptr++) + { + if ((*vfield_ptr)->stored_in_db) + { + thd->lex->unit.insert_table_with_stored_vcol= table; + break; + } + } + } + uint tot_length=0; bool use_blobs= 0, use_vars= 0; List_iterator_fast<Item> it(fields_vars); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index d3e99e17275..8567587a48a 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6848,6 +6848,8 @@ void THD::reset_for_next_command() thd->reset_current_stmt_binlog_format_row(); thd->binlog_unsafe_warning_flags= 0; + thd->save_prep_leaf_list= false; + DBUG_PRINT("debug", ("is_current_stmt_binlog_format_row(): %d", thd->is_current_stmt_binlog_format_row())); @@ -8327,6 +8329,8 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables) */ for (table= tables; table; table= table->next_local) { + if (table->is_jtbm()) + continue; if (table->derived) table->grant.privilege= SELECT_ACL; else if ((check_access(thd, UPDATE_ACL, table->db, diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index a43b8c7484a..6d8268efe86 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1077,7 +1077,7 @@ static bool plugin_add(MEM_ROOT *tmp_root, if (name->str && plugin_find_internal(name, MYSQL_ANY_PLUGIN)) { - report_error(report, ER_UDF_EXISTS, name->str); + report_error(report, ER_PLUGIN_INSTALLED, name->str); DBUG_RETURN(TRUE); } /* Clear the whole struct to catch future extensions. */ @@ -1577,6 +1577,9 @@ int plugin_init(int *argc, char **argv, int flags) /* First we register builtin plugins */ + if (global_system_variables.log_warnings >= 9) + sql_print_information("Initializing built-in plugins"); + for (builtins= mysql_mandatory_plugins; *builtins || mandatory; builtins++) { if (!*builtins) @@ -1640,6 +1643,8 @@ int plugin_init(int *argc, char **argv, int flags) { I_List_iterator<i_string> iter(opt_plugin_load_list); i_string *item; + if (global_system_variables.log_warnings >= 9) + sql_print_information("Initializing plugins specified on the command line"); while (NULL != (item= iter++)) plugin_load_list(&tmp_root, item->ptr); @@ -1763,6 +1768,9 @@ static void plugin_load(MEM_ROOT *tmp_root) bool result; DBUG_ENTER("plugin_load"); + if (global_system_variables.log_warnings >= 9) + sql_print_information("Initializing installed plugins"); + new_thd->thread_stack= (char*) &tables; new_thd->store_globals(); new_thd->db= my_strdup("mysql", MYF(0)); @@ -1811,9 +1819,7 @@ static void plugin_load(MEM_ROOT *tmp_root) the mutex here to satisfy the assert */ mysql_mutex_lock(&LOCK_plugin); - if (plugin_add(tmp_root, &name, &dl, REPORT_TO_LOG)) - sql_print_warning("Couldn't load plugin named '%s' with soname '%s'.", - str_name.c_ptr(), str_dl.c_ptr()); + plugin_add(tmp_root, &name, &dl, REPORT_TO_LOG); free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE)); mysql_mutex_unlock(&LOCK_plugin); } diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 6d03d23f800..71e53dd86a2 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -79,8 +79,7 @@ fake_event_header(String* packet, Log_event_type event_type, ulong extra_len, } if (*do_checksum) { - *crc= my_checksum(0L, NULL, 0); - *crc= my_checksum(*crc, (uchar*)header, sizeof(header)); + *crc= my_checksum(0, (uchar*)header, sizeof(header)); } return 0; } @@ -811,8 +810,8 @@ static int send_heartbeat_event(binlog_send_info *info, if (do_checksum) { char b[BINLOG_CHECKSUM_LEN]; - ha_checksum crc= my_checksum(0L, NULL, 0); - crc= my_checksum(crc, (uchar*) header, sizeof(header)); + ha_checksum crc; + crc= my_checksum(0, (uchar*) header, sizeof(header)); crc= my_checksum(crc, (uchar*) p, ident_len); int4store(b, crc); packet->append(b, sizeof(b)); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index a15dd56fa75..b489756c784 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1550,6 +1550,9 @@ TODO: make view to decide if it is possible to write to WHERE directly or make S /* Cache constant expressions in WHERE, HAVING, ON clauses. */ cache_const_exprs(); + if (setup_semijoin_loosescan(this)) + DBUG_RETURN(1); + if (make_join_select(this, select, conds)) { zero_result_cause= @@ -5243,6 +5246,8 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, KEY_FIELD *key_fields, *end, *field; uint sz; uint m= MY_MAX(select_lex->max_equal_elems,1); + DBUG_ENTER("update_ref_and_keys"); + DBUG_PRINT("enter", ("normal_tables: %llx", normal_tables)); SELECT_LEX *sel=thd->lex->current_select; sel->cond_count= 0; @@ -5289,7 +5294,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, sz= MY_MAX(sizeof(KEY_FIELD),sizeof(SARGABLE_PARAM))* ((sel->cond_count*2 + sel->between_count)*m+1); if (!(key_fields=(KEY_FIELD*) thd->alloc(sz))) - return TRUE; /* purecov: inspected */ + DBUG_RETURN(TRUE); /* purecov: inspected */ and_level= 0; field= end= key_fields; *sargables= (SARGABLE_PARAM *) key_fields + @@ -5300,7 +5305,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, if (my_init_dynamic_array2(keyuse, sizeof(KEYUSE), thd->alloc(sizeof(KEYUSE) * 20), 20, 64, MYF(MY_THREAD_SPECIFIC))) - return TRUE; + DBUG_RETURN(TRUE); if (cond) { @@ -5351,16 +5356,16 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, for ( ; field != end ; field++) { if (add_key_part(keyuse,field)) - return TRUE; + DBUG_RETURN(TRUE); } if (select_lex->ftfunc_list->elements) { if (add_ft_keys(keyuse,join_tab,cond,normal_tables)) - return TRUE; + DBUG_RETURN(TRUE); } - return FALSE; + DBUG_RETURN(FALSE); } @@ -9778,9 +9783,14 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) Check again if we should use an index. We could have used an column from a previous table in the index if we are using limit and this is the first table + + (1) - Don't switch the used index if we are using semi-join + LooseScan on this table. Using different index will not + produce the desired ordering and de-duplication. */ if (!tab->table->is_filled_at_execution() && + !tab->loosescan_match_tab && // (1) ((cond && (!tab->keys.is_subset(tab->const_keys) && i > 0)) || (!tab->const_keys.is_clear_all() && i == join->const_tables && join->unit->select_limit_cnt < @@ -21906,7 +21916,7 @@ setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, Item_field *field; int cur_pos_in_select_list= 0; List_iterator<Item> li(fields); - List_iterator<Item_field> naf_it(thd->lex->current_select->non_agg_fields); + List_iterator<Item_field> naf_it(thd->lex->current_select->join->non_agg_fields); field= naf_it++; while (field && (item=li++)) diff --git a/sql/sql_select.h b/sql/sql_select.h index ca69c0c23eb..57c66bae8e2 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -745,8 +745,7 @@ public: struct st_position *pos, struct st_position *loose_scan_pos); friend bool get_best_combination(JOIN *join); - friend int setup_semijoin_dups_elimination(JOIN *join, ulonglong options, - uint no_jbuf_after); + friend int setup_semijoin_loosescan(JOIN *join); friend void fix_semijoin_strategies_for_picked_join_order(JOIN *join); }; @@ -963,6 +962,9 @@ public: Item *pre_sort_idx_pushed_cond; void clean_pre_sort_join_tab(); + /* List of fields that aren't under an aggregate function */ + List<Item_field> non_agg_fields; + /* For "Using temporary+Using filesort" queries, JOIN::join_tab can point to either: @@ -1382,6 +1384,7 @@ public: all_fields= fields_arg; if (&fields_list != &fields_arg) /* Avoid valgrind-warning */ fields_list= fields_arg; + non_agg_fields.empty(); bzero((char*) &keyuse,sizeof(keyuse)); tmp_table_param.init(); tmp_table_param.end_write_records= HA_POS_ERROR; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index ddad6096bd8..28e623f3af1 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -3363,7 +3363,10 @@ void calc_sum_of_all_status(STATUS_VAR *to) /* Add to this status from existing threads */ while ((tmp= it++)) - add_to_status(to, &tmp->status_var); + { + if (!tmp->status_in_global) + add_to_status(to, &tmp->status_var); + } mysql_mutex_unlock(&LOCK_thread_count); DBUG_VOID_RETURN; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 2ce4a08410d..da7d144f3d8 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4680,12 +4680,12 @@ int create_table_impl(THD *thd, bool table_creation_was_logged= tmp_table->s->table_creation_was_logged; if (options.or_replace()) { - bool is_trans; + bool tmp; /* We are using CREATE OR REPLACE on an existing temporary table Remove the old table so that we can re-create it. */ - if (drop_temporary_table(thd, tmp_table, &is_trans)) + if (drop_temporary_table(thd, tmp_table, &tmp)) goto err; } else if (options.if_not_exists()) diff --git a/sql/sql_test.cc b/sql/sql_test.cc index ec65bd037b9..8e7525893eb 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -224,7 +224,7 @@ TEST_join(JOIN *join) #define FT_KEYPART (MAX_FIELDS+10) -void print_keyuse(KEYUSE *keyuse) +static void print_keyuse(KEYUSE *keyuse) { char buff[256]; char buf2[64]; @@ -242,14 +242,11 @@ void print_keyuse(KEYUSE *keyuse) else fieldname= key_info->key_part[keyuse->keypart].field->field_name; ll2str(keyuse->used_tables, buf2, 16, 0); - DBUG_LOCK_FILE; fprintf(DBUG_FILE, "KEYUSE: %s.%s=%s optimize: %u used_tables: %s " "ref_table_rows: %lu keypart_map: %0lx\n", keyuse->table->alias.c_ptr(), fieldname, str.ptr(), (uint) keyuse->optimize, buf2, (ulong) keyuse->ref_table_rows, (ulong) keyuse->keypart_map); - DBUG_UNLOCK_FILE; - //key_part_map keypart_map; --?? there can be several? } @@ -258,9 +255,9 @@ void print_keyuse_array(DYNAMIC_ARRAY *keyuse_array) { DBUG_LOCK_FILE; fprintf(DBUG_FILE, "KEYUSE array (%d elements)\n", keyuse_array->elements); - DBUG_UNLOCK_FILE; for(uint i=0; i < keyuse_array->elements; i++) print_keyuse((KEYUSE*)dynamic_array_ptr(keyuse_array, i)); + DBUG_UNLOCK_FILE; } diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 356f68693bd..c8350838ee8 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -1178,7 +1178,6 @@ bool st_select_lex::cleanup() { error= (bool) ((uint) error | (uint) lex_unit->cleanup()); } - non_agg_fields.empty(); inner_refs_list.empty(); exclude_from_table_unique_test= FALSE; DBUG_RETURN(error); @@ -1189,6 +1188,7 @@ void st_select_lex::cleanup_all_joins(bool full) { SELECT_LEX_UNIT *unit; SELECT_LEX *sl; + DBUG_ENTER("st_select_lex::cleanup_all_joins"); if (join) join->cleanup(full); @@ -1196,6 +1196,7 @@ void st_select_lex::cleanup_all_joins(bool full) for (unit= first_inner_unit(); unit; unit= unit->next_unit()) for (sl= unit->first_select(); sl; sl= sl->next_select()) sl->cleanup_all_joins(full); + DBUG_VOID_RETURN; } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 0f17716974c..7a66cc3734c 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1186,7 +1186,7 @@ bool unsafe_key_update(List<TABLE_LIST> leaves, table_map tables_for_update) while ((tl= it++)) { - if (tl->table->map & tables_for_update) + if (!tl->is_jtbm() && (tl->table->map & tables_for_update)) { TABLE *table1= tl->table; bool primkey_clustered= (table1->file->primary_key_is_clustered() && @@ -1203,6 +1203,8 @@ bool unsafe_key_update(List<TABLE_LIST> leaves, table_map tables_for_update) it2.rewind(); while ((tl2= it2++)) { + if (tl2->is_jtbm()) + continue; /* Look at "next" tables only since all previous tables have already been checked @@ -1434,6 +1436,9 @@ int mysql_multi_update_prepare(THD *thd) { TABLE *table= tl->table; + if (tl->is_jtbm()) + continue; + /* if table will be updated then check that it is unique */ if (table->map & tables_for_update) { @@ -1482,6 +1487,8 @@ int mysql_multi_update_prepare(THD *thd) for (tl= table_list; tl; tl= tl->next_local) { bool not_used= false; + if (tl->is_jtbm()) + continue; if (multi_update_check_table_access(thd, tl, tables_for_update, ¬_used)) DBUG_RETURN(TRUE); } @@ -1489,6 +1496,8 @@ int mysql_multi_update_prepare(THD *thd) /* check single table update for view compound from several tables */ for (tl= table_list; tl; tl= tl->next_local) { + if (tl->is_jtbm()) + continue; if (tl->is_merged_derived()) { TABLE_LIST *for_update= 0; @@ -1518,6 +1527,8 @@ int mysql_multi_update_prepare(THD *thd) ti.rewind(); while ((tl= ti++)) { + if (tl->is_jtbm()) + continue; TABLE *table= tl->table; TABLE_LIST *tlist; if (!(tlist= tl->top_table())->derived) @@ -1661,6 +1672,9 @@ int multi_update::prepare(List<Item> ¬_used_values, */ while ((table_ref= ti++)) { + if (table_ref->is_jtbm()) + continue; + TABLE *table= table_ref->table; if (tables_to_update & table->map) { @@ -1680,6 +1694,9 @@ int multi_update::prepare(List<Item> ¬_used_values, ti.rewind(); while ((table_ref= ti++)) { + if (table_ref->is_jtbm()) + continue; + TABLE *table= table_ref->table; if (tables_to_update & table->map) { @@ -1710,6 +1727,8 @@ int multi_update::prepare(List<Item> ¬_used_values, while ((table_ref= ti++)) { /* TODO: add support of view of join support */ + if (table_ref->is_jtbm()) + continue; TABLE *table=table_ref->table; leaf_table_count++; if (tables_to_update & table->map) diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 0a04d20ae4b..396b4c0ae83 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -325,6 +325,14 @@ static Sys_var_long Sys_pfs_digest_size( DEFAULT(-1), BLOCK_SIZE(1)); +static Sys_var_long Sys_pfs_max_digest_length( + "performance_schema_max_digest_length", + "Maximum length considered for digest text, when stored in performance_schema tables.", + PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_max_digest_length), + CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024 * 1024), + DEFAULT(1024), + BLOCK_SIZE(1)); + static Sys_var_long Sys_pfs_connect_attrs_size( "performance_schema_session_connect_attrs_size", "Size of session attribute string buffer per thread." @@ -1349,7 +1357,7 @@ static Sys_var_ulong Sys_max_connect_errors( static Sys_var_uint Sys_max_digest_length( "max_digest_length", "Maximum length considered for digest text.", - PARSED_EARLY READ_ONLY GLOBAL_VAR(max_digest_length), + READ_ONLY GLOBAL_VAR(max_digest_length), CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024 * 1024), DEFAULT(1024), BLOCK_SIZE(1)); diff --git a/sql/table.cc b/sql/table.cc index f233fd19860..76cb4b86a81 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -5301,7 +5301,7 @@ Item *Field_iterator_table::create_item(THD *thd) if (item && thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY && !thd->lex->in_sum_func && select->cur_pos_in_select_list != UNDEF_POS) { - select->non_agg_fields.push_back(item); + select->join->non_agg_fields.push_back(item); item->marker= select->cur_pos_in_select_list; select->set_non_agg_field_used(true); } @@ -5366,6 +5366,12 @@ Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref, item->maybe_null= TRUE; /* Save item in case we will need to fall back to materialization. */ view->used_items.push_front(item, thd->mem_root); + /* + If we create this reference on persistent memory then it should be + present in persistent list + */ + if (thd->mem_root == thd->stmt_arena->mem_root) + view->persistent_used_items.push_front(item, thd->mem_root); DBUG_RETURN(item); } @@ -7086,6 +7092,7 @@ bool TABLE_LIST::handle_derived(LEX *lex, uint phases) { SELECT_LEX_UNIT *unit; DBUG_ENTER("handle_derived"); + DBUG_PRINT("enter", ("phases: 0x%x", phases)); if ((unit= get_unit())) { for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select()) |