diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2021-05-07 15:00:27 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2021-05-07 15:00:27 +0300 |
commit | 916b237b3f6ee4d8e113d480c53bca232cadbb7b (patch) | |
tree | 238054b502f633afcb88a3fb1929d860a7e96e91 /sql | |
parent | a04202673fe8f5a89a88e543e3e0f5b9de5215d2 (diff) | |
parent | 35977e81f967ebe10db8ee40703801e693b2a0f4 (diff) | |
download | mariadb-git-916b237b3f6ee4d8e113d480c53bca232cadbb7b.tar.gz |
Merge 10.5 into 10.6
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item_create.cc | 15 | ||||
-rw-r--r-- | sql/item_create.h | 1 | ||||
-rw-r--r-- | sql/item_vers.cc | 16 | ||||
-rw-r--r-- | sql/item_vers.h | 30 | ||||
-rw-r--r-- | sql/log_event.h | 13 | ||||
-rw-r--r-- | sql/log_event_server.cc | 16 | ||||
-rw-r--r-- | sql/sp_head.h | 2 | ||||
-rw-r--r-- | sql/sql_acl.cc | 6 | ||||
-rw-r--r-- | sql/sql_base.cc | 3 | ||||
-rw-r--r-- | sql/sql_class.cc | 16 | ||||
-rw-r--r-- | sql/sql_class.h | 4 | ||||
-rw-r--r-- | sql/sql_derived.cc | 6 | ||||
-rw-r--r-- | sql/sql_insert.cc | 5 | ||||
-rw-r--r-- | sql/sql_lex.cc | 74 | ||||
-rw-r--r-- | sql/sql_lex.h | 4 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 16 | ||||
-rw-r--r-- | sql/sql_repl.cc | 31 | ||||
-rw-r--r-- | sql/sql_select.cc | 11 | ||||
-rw-r--r-- | sql/sql_select.h | 6 | ||||
-rw-r--r-- | sql/sql_show.cc | 2 | ||||
-rw-r--r-- | sql/sql_table.cc | 10 | ||||
-rw-r--r-- | sql/sql_udf.cc | 6 | ||||
-rw-r--r-- | sql/sql_update.cc | 5 |
23 files changed, 206 insertions, 92 deletions
diff --git a/sql/item_create.cc b/sql/item_create.cc index cff44c6f61a..3a08add73b7 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -5664,6 +5664,21 @@ int item_create_append(Native_func_registry array[]) DBUG_RETURN(0); } +int item_create_remove(Native_func_registry array[]) +{ + Native_func_registry *func; + + DBUG_ENTER("item_create_remove"); + + for (func= array; func->builder != NULL; func++) + { + if (my_hash_delete(& native_functions_hash, (uchar*) func)) + DBUG_RETURN(1); + } + + DBUG_RETURN(0); +} + /* Empty the hash table for native functions. Note: this code is not thread safe, and is intended to be used at server diff --git a/sql/item_create.h b/sql/item_create.h index c9bdb23dffe..c04adad469c 100644 --- a/sql/item_create.h +++ b/sql/item_create.h @@ -304,6 +304,7 @@ struct Native_func_registry int item_create_init(); int item_create_append(Native_func_registry array[]); +int item_create_remove(Native_func_registry array[]); void item_create_cleanup(); Item *create_func_dyncol_create(THD *thd, List<DYNCALL_CREATE_DEF> &list); diff --git a/sql/item_vers.cc b/sql/item_vers.cc index c8f1c793895..792c434b8c3 100644 --- a/sql/item_vers.cc +++ b/sql/item_vers.cc @@ -26,6 +26,22 @@ #include "tztime.h" #include "item.h" +bool Item_func_history::val_bool() +{ + Item_field *f= static_cast<Item_field *>(args[0]); + DBUG_ASSERT(f->fixed); + DBUG_ASSERT(f->field->flags & VERS_SYS_END_FLAG); + return !f->field->is_max(); +} + +void Item_func_history::print(String *str, enum_query_type query_type) +{ + str->append(func_name()); + str->append('('); + args[0]->print(str, query_type); + str->append(')'); +} + Item_func_trt_ts::Item_func_trt_ts(THD *thd, Item* a, TR_table::field_id_t _trt_field) : Item_datetimefunc(thd, a), trt_field(_trt_field) diff --git a/sql/item_vers.h b/sql/item_vers.h index a42b5a033f2..0799d04a0bc 100644 --- a/sql/item_vers.h +++ b/sql/item_vers.h @@ -22,6 +22,36 @@ #pragma interface /* gcc class implementation */ #endif +class Item_func_history: public Item_bool_func +{ +public: + /* + @param a Item_field for row_end system field + */ + Item_func_history(THD *thd, Item *a): Item_bool_func(thd, a) + { + DBUG_ASSERT(a->type() == Item::FIELD_ITEM); + } + + virtual bool val_bool(); + virtual longlong val_int() + { + return (val_bool() ? 1 : 0); + } + bool fix_length_and_dec() + { + maybe_null= 0; + null_value= 0; + decimals= 0; + max_length= 1; + return FALSE; + } + virtual const char* func_name() const { return "is_history"; } + virtual void print(String *str, enum_query_type query_type); + Item *get_copy(THD *thd) + { return get_item_copy<Item_func_history>(thd, this); } +}; + class Item_func_trt_ts: public Item_datetimefunc { TR_table::field_id_t trt_field; diff --git a/sql/log_event.h b/sql/log_event.h index 4e193232f4b..3e08653a211 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -576,6 +576,14 @@ class String; #define MARIA_SLAVE_CAPABILITY_MINE MARIA_SLAVE_CAPABILITY_GTID +/* + When the size of 'log_pos' within Heartbeat_log_event exceeds UINT32_MAX it + cannot be accommodated in common_header, as 'log_pos' is of 4 bytes size. In + such cases, sub_header, of size 8 bytes will hold larger 'log_pos' value. +*/ +#define HB_SUB_HEADER_LEN 8 + + /** @enum Log_event_type @@ -5718,12 +5726,13 @@ bool copy_cache_to_file_wrapped(IO_CACHE *body, class Heartbeat_log_event: public Log_event { public: - Heartbeat_log_event(const char* buf, uint event_len, + uint8 hb_flags; + Heartbeat_log_event(const char* buf, ulong event_len, const Format_description_log_event* description_event); Log_event_type get_type_code() { return HEARTBEAT_LOG_EVENT; } bool is_valid() const { - return (log_ident != NULL && + return (log_ident != NULL && ident_len <= FN_REFLEN-1 && log_pos >= BIN_LOG_HEADER_SIZE); } const char * get_log_ident() { return log_ident; } diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index bbb824ef8ee..b4e61e1fbc4 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -8528,14 +8528,22 @@ void Ignorable_log_event::pack_info(Protocol *protocol) #if defined(HAVE_REPLICATION) -Heartbeat_log_event::Heartbeat_log_event(const char* buf, uint event_len, +Heartbeat_log_event::Heartbeat_log_event(const char* buf, ulong event_len, const Format_description_log_event* description_event) :Log_event(buf, description_event) { uint8 header_size= description_event->common_header_len; - ident_len = event_len - header_size; - set_if_smaller(ident_len,FN_REFLEN-1); - log_ident= buf + header_size; + if (log_pos == 0) + { + log_pos= uint8korr(buf + header_size); + log_ident= buf + header_size + HB_SUB_HEADER_LEN; + ident_len= event_len - (header_size + HB_SUB_HEADER_LEN); + } + else + { + log_ident= buf + header_size; + ident_len = event_len - header_size; + } } #endif diff --git a/sql/sp_head.h b/sql/sp_head.h index 913be1aace7..34dd09fd88f 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -117,7 +117,7 @@ public: bool use_explicit_name) : Database_qualified_name(db, name), m_explicit_name(use_explicit_name) { - if (lower_case_table_names && m_db.str) + if (lower_case_table_names && m_db.length) m_db.length= my_casedn_str(files_charset_info, (char*) m_db.str); } diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 345ed4d781a..7b8b2a7ec55 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2196,7 +2196,11 @@ static bool validate_password(THD *thd, const LEX_CSTRING &user, else { if (!thd->slave_thread && - strict_password_validation && has_validation_plugins()) + strict_password_validation && has_validation_plugins() +#ifdef WITH_WSREP + && !thd->wsrep_applier +#endif + ) { my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--strict-password-validation"); return true; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 5f074b484f4..f76ac2e9fe5 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -5306,7 +5306,6 @@ bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags, uint counter; MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint(); DBUG_ENTER("open_normal_and_derived_tables"); - DBUG_ASSERT(!thd->fill_derived_tables()); if (open_tables(thd, &tables, &counter, flags, &prelocking_strategy) || mysql_handle_derived(thd->lex, dt_phases)) goto end; @@ -5364,7 +5363,7 @@ bool open_tables_only_view_structure(THD *thd, TABLE_LIST *table_list, MYSQL_OPEN_GET_NEW_TABLE | (can_deadlock ? MYSQL_OPEN_FAIL_ON_MDL_CONFLICT : 0)), - DT_INIT | DT_PREPARE | DT_CREATE)); + DT_INIT | DT_PREPARE)); /* Restore old value of sql_command back as it is being looked at in process_table() function. diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 9c1d1560955..095988b5e00 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -335,17 +335,6 @@ THD *thd_get_current_thd() return current_thd; } -/** - Clear errors from the previous THD - - @param thd THD object -*/ -void thd_clear_errors(THD *thd) -{ - my_errno= 0; - thd->mysys_var->abort= 0; -} - extern "C" unsigned long long thd_query_id(const MYSQL_THD thd) { @@ -1440,7 +1429,10 @@ void THD::change_user(void) cleanup(); cleanup_done= 0; reset_killed(); - thd_clear_errors(this); + /* Clear errors from the previous THD */ + my_errno= 0; + if (mysys_var) + mysys_var->abort= 0; /* Clear warnings. */ if (!get_stmt_da()->is_warning_info_empty()) diff --git a/sql/sql_class.h b/sql/sql_class.h index 99811c9cf81..031fff71ec8 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -4024,10 +4024,6 @@ public: give_protection_error(); return TRUE; } - inline bool fill_derived_tables() - { - return !stmt_arena->is_stmt_prepare() && !lex->only_view_structure(); - } inline bool fill_information_schema_tables() { return !stmt_arena->is_stmt_prepare(); diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index f753f9af6a6..1d139f087e1 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -73,7 +73,6 @@ bool mysql_handle_derived(LEX *lex, uint phases) { bool res= FALSE; - THD *thd= lex->thd; DBUG_ENTER("mysql_handle_derived"); DBUG_PRINT("enter", ("phases: 0x%x", phases)); if (!lex->derived_tables) @@ -88,8 +87,6 @@ mysql_handle_derived(LEX *lex, uint phases) break; if (!(phases & phase_flag)) continue; - if (phase_flag >= DT_CREATE && !thd->fill_derived_tables()) - break; for (SELECT_LEX *sl= lex->all_selects_list; sl && !res; @@ -173,7 +170,6 @@ bool mysql_handle_single_derived(LEX *lex, TABLE_LIST *derived, uint phases) { bool res= FALSE; - THD *thd= lex->thd; uint8 allowed_phases= (derived->is_merged_derived() ? DT_PHASES_MERGE : DT_PHASES_MATERIALIZE); DBUG_ENTER("mysql_handle_single_derived"); @@ -200,8 +196,6 @@ mysql_handle_single_derived(LEX *lex, TABLE_LIST *derived, uint phases) if (phase_flag != DT_PREPARE && !(allowed_phases & phase_flag)) continue; - if (phase_flag >= DT_CREATE && !thd->fill_derived_tables()) - break; if ((res= (*processors[phase])(lex->thd, lex, derived))) break; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 041a64d402d..381d0be4384 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1868,9 +1868,10 @@ int write_record(THD *thd, TABLE *table, COPY_INFO *info, select_result *sink) in handler methods for the just read row in record[1]. */ table->move_fields(table->field, table->record[1], table->record[0]); - if (table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_REPLACE)) - goto err; + int verr = table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_REPLACE); table->move_fields(table->field, table->record[0], table->record[1]); + if (verr) + goto err; } if (info->handle_duplicates == DUP_UPDATE) { diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index f4c764bbca8..5779328953f 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1323,15 +1323,15 @@ void lex_end(LEX *lex) DBUG_ENTER("lex_end"); DBUG_PRINT("enter", ("lex: %p", lex)); - lex_end_stage1(lex); - lex_end_stage2(lex); + lex_unlock_plugins(lex); + lex_end_nops(lex); DBUG_VOID_RETURN; } -void lex_end_stage1(LEX *lex) +void lex_unlock_plugins(LEX *lex) { - DBUG_ENTER("lex_end_stage1"); + DBUG_ENTER("lex_unlock_plugins"); /* release used plugins */ if (lex->plugins.elements) /* No function call and no mutex if no plugins. */ @@ -1340,33 +1340,23 @@ void lex_end_stage1(LEX *lex) lex->plugins.elements); } reset_dynamic(&lex->plugins); - - if (lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_PREPARE) - { - /* - Don't delete lex->sphead, it'll be needed for EXECUTE. - Note that of all statements that populate lex->sphead - only SQLCOM_COMPOUND can be PREPAREd - */ - DBUG_ASSERT(lex->sphead == 0 || lex->sql_command == SQLCOM_COMPOUND); - } - else - { - sp_head::destroy(lex->sphead); - lex->sphead= NULL; - } - DBUG_VOID_RETURN; } /* + Don't delete lex->sphead, it'll be needed for EXECUTE. + Note that of all statements that populate lex->sphead + only SQLCOM_COMPOUND can be PREPAREd + MASTER INFO parameters (or state) is normally cleared towards the end of a statement. But in case of PS, the state needs to be preserved during its lifetime and should only be cleared on PS close or deallocation. */ -void lex_end_stage2(LEX *lex) +void lex_end_nops(LEX *lex) { - DBUG_ENTER("lex_end_stage2"); + DBUG_ENTER("lex_end_nops"); + sp_head::destroy(lex->sphead); + lex->sphead= NULL; /* Reset LEX_MASTER_INFO */ lex->mi.reset(lex->sql_command == SQLCOM_CHANGE_MASTER); @@ -2772,6 +2762,11 @@ int Lex_input_stream::scan_ident_middle(THD *thd, Lex_ident_cli_st *str, yySkip(); // next state does a unget } + yyUnget(); // ptr points now after last token char + str->set_ident(m_tok_start, length, is_8bit); + m_cpp_text_start= m_cpp_tok_start; + m_cpp_text_end= m_cpp_text_start + length; + /* Note: "SELECT _bla AS 'alias'" _bla should be considered as a IDENT if charset haven't been found. @@ -2781,28 +2776,17 @@ int Lex_input_stream::scan_ident_middle(THD *thd, Lex_ident_cli_st *str, DBUG_ASSERT(length > 0); if (resolve_introducer && m_tok_start[0] == '_') { - - yyUnget(); // ptr points now after last token char - str->set_ident(m_tok_start, length, false); - - m_cpp_text_start= m_cpp_tok_start; - m_cpp_text_end= m_cpp_text_start + length; - body_utf8_append(m_cpp_text_start, m_cpp_tok_start + length); ErrConvString csname(str->str + 1, str->length - 1, &my_charset_bin); CHARSET_INFO *cs= get_charset_by_csname(csname.ptr(), MY_CS_PRIMARY, MYF(0)); if (cs) { + body_utf8_append(m_cpp_text_start, m_cpp_tok_start + length); *introducer= cs; return UNDERSCORE_CHARSET; } - return IDENT; } - yyUnget(); // ptr points now after last token char - str->set_ident(m_tok_start, length, is_8bit); - m_cpp_text_start= m_cpp_tok_start; - m_cpp_text_end= m_cpp_text_start + length; body_utf8_append(m_cpp_text_start); body_utf8_append_ident(thd, str, m_cpp_text_end); return is_8bit ? IDENT_QUOTED : IDENT; @@ -6451,13 +6435,33 @@ void LEX::sp_variable_declarations_init(THD *thd, int nvars) bool LEX::sp_variable_declarations_set_default(THD *thd, int nvars, Item *dflt_value_item) { - if (!dflt_value_item && + bool has_default_clause= dflt_value_item != NULL; + if (!has_default_clause && unlikely(!(dflt_value_item= new (thd->mem_root) Item_null(thd)))) return true; + sp_variable *first_spvar = NULL; + for (uint i= 0 ; i < (uint) nvars ; i++) { sp_variable *spvar= spcont->get_last_context_variable((uint) nvars - 1 - i); + + if (i == 0) { + first_spvar = spvar; + } else if (has_default_clause) { + Item_splocal *item = + new (thd->mem_root) + Item_splocal(thd, &sp_rcontext_handler_local, + &first_spvar->name, first_spvar->offset, + first_spvar->type_handler(), 0, 0); + if (item == NULL) + return true; // OOM +#ifndef DBUG_OFF + item->m_sp = sphead; +#endif + dflt_value_item = item; + } + bool last= i + 1 == (uint) nvars; spvar->default_value= dflt_value_item; /* The last instruction is responsible for freeing LEX. */ diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 2eb1d5b7dc9..f1aeba8b4b1 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -5045,8 +5045,8 @@ extern void lex_init(void); extern void lex_free(void); extern void lex_start(THD *thd); extern void lex_end(LEX *lex); -extern void lex_end_stage1(LEX *lex); -extern void lex_end_stage2(LEX *lex); +extern void lex_end_nops(LEX *lex); +extern void lex_unlock_plugins(LEX *lex); void end_lex_with_single_table(THD *thd, TABLE *table, LEX *old_lex); int init_lex_with_single_table(THD *thd, TABLE *table, LEX *lex); extern int MYSQLlex(union YYSTYPE *yylval, THD *thd); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 6a9cc8eed10..c3dd0858d64 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1556,7 +1556,7 @@ static int mysql_test_select(Prepared_statement *stmt, } if (open_normal_and_derived_tables(thd, tables, MYSQL_OPEN_FORCE_SHARED_MDL, - DT_INIT | DT_PREPARE | DT_CREATE)) + DT_INIT | DT_PREPARE)) goto error; thd->lex->used_tables= 0; // Updated by setup_fields @@ -1618,7 +1618,7 @@ static bool mysql_test_do_fields(Prepared_statement *stmt, DBUG_RETURN(TRUE); if (open_normal_and_derived_tables(thd, tables, MYSQL_OPEN_FORCE_SHARED_MDL, - DT_INIT | DT_PREPARE | DT_CREATE)) + DT_INIT | DT_PREPARE)) DBUG_RETURN(TRUE); DBUG_RETURN(setup_fields(thd, Ref_ptr_array(), *values, COLUMNS_READ, 0, NULL, 0)); @@ -1650,7 +1650,7 @@ static bool mysql_test_set_fields(Prepared_statement *stmt, if ((tables && check_table_access(thd, SELECT_ACL, tables, FALSE, UINT_MAX, FALSE)) || open_normal_and_derived_tables(thd, tables, MYSQL_OPEN_FORCE_SHARED_MDL, - DT_INIT | DT_PREPARE | DT_CREATE)) + DT_INIT | DT_PREPARE)) goto error; while ((var= it++)) @@ -1814,7 +1814,7 @@ static bool mysql_test_create_table(Prepared_statement *stmt) if (open_normal_and_derived_tables(stmt->thd, lex->query_tables, MYSQL_OPEN_FORCE_SHARED_MDL, - DT_INIT | DT_PREPARE | DT_CREATE)) + DT_INIT | DT_PREPARE)) DBUG_RETURN(TRUE); select_lex->context.resolve_in_select_list= TRUE; @@ -4343,8 +4343,10 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) thd->release_transactional_locks(); } - /* Preserve CHANGE MASTER attributes */ - lex_end_stage1(lex); + /* Preserve locked plugins for SET */ + if (lex->sql_command != SQLCOM_SET_OPTION) + lex_unlock_plugins(lex); + cleanup_stmt(); thd->restore_backup_statement(this, &stmt_backup); thd->stmt_arena= old_stmt_arena; @@ -5190,7 +5192,7 @@ void Prepared_statement::deallocate_immediate() status_var_increment(thd->status_var.com_stmt_close); /* It should now be safe to reset CHANGE MASTER parameters */ - lex_end_stage2(lex); + lex_end(lex); } diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index ce270351dc3..ff2faca5ecf 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -32,6 +32,7 @@ #include "semisync_slave.h" #include "mysys_err.h" + enum enum_gtid_until_state { GTID_UNTIL_NOT_DONE, GTID_UNTIL_STOP_AFTER_STANDALONE, @@ -816,7 +817,7 @@ get_slave_until_gtid(THD *thd, String *out_str) @param event_coordinates binlog file name and position of the last real event master sent from binlog - @note + @note Among three essential pieces of heartbeat data Log_event::when is computed locally. The error to send is serious and should force terminating @@ -830,6 +831,8 @@ static int send_heartbeat_event(binlog_send_info *info, DBUG_ENTER("send_heartbeat_event"); ulong ev_offset; + char sub_header_buf[HB_SUB_HEADER_LEN]; + bool sub_header_in_use=false; if (reset_transmit_packet(info, info->flags, &ev_offset, &info->errmsg)) DBUG_RETURN(1); @@ -850,18 +853,38 @@ static int send_heartbeat_event(binlog_send_info *info, size_t event_len = ident_len + LOG_EVENT_HEADER_LEN + (do_checksum ? BINLOG_CHECKSUM_LEN : 0); int4store(header + SERVER_ID_OFFSET, global_system_variables.server_id); + DBUG_EXECUTE_IF("simulate_pos_4G", + { + const_cast<event_coordinates *>(coord)->pos= (UINT_MAX32 + (ulong)1); + DBUG_SET("-d, simulate_pos_4G"); + };); + if (coord->pos <= UINT_MAX32) + { + int4store(header + LOG_POS_OFFSET, coord->pos); // log_pos + } + else + { + // Set common_header.log_pos=0 to indicate its overflow + int4store(header + LOG_POS_OFFSET, 0); + sub_header_in_use= true; + int8store(sub_header_buf, coord->pos); + event_len+= HB_SUB_HEADER_LEN; + } + int4store(header + EVENT_LEN_OFFSET, event_len); int2store(header + FLAGS_OFFSET, 0); - int4store(header + LOG_POS_OFFSET, coord->pos); // log_pos - packet->append(header, sizeof(header)); - packet->append(p, ident_len); // log_file_name + if (sub_header_in_use) + packet->append(sub_header_buf, sizeof(sub_header_buf)); + packet->append(p, ident_len); // log_file_name if (do_checksum) { char b[BINLOG_CHECKSUM_LEN]; ha_checksum crc= my_checksum(0, (uchar*) header, sizeof(header)); + if (sub_header_in_use) + crc= my_checksum(crc, (uchar*) sub_header_buf, sizeof(sub_header_buf)); 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 73436e8aec4..4b03bd056f3 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -862,7 +862,8 @@ Item* period_get_condition(THD *thd, TABLE_LIST *table, SELECT_LEX *select, cond3= newx Item_func_le(thd, conds->start.item, conds->end.item); break; case SYSTEM_TIME_BEFORE: - cond1= newx Item_func_lt(thd, conds->field_end, conds->start.item); + cond1= newx Item_func_history(thd, conds->field_end); + cond2= newx Item_func_lt(thd, conds->field_end, conds->start.item); break; default: DBUG_ASSERT(0); @@ -915,7 +916,8 @@ Item* period_get_condition(THD *thd, TABLE_LIST *table, SELECT_LEX *select, cond3= newx Item_func_le(thd, conds->start.item, conds->end.item); break; case SYSTEM_TIME_BEFORE: - cond1= newx Item_func_trt_trx_sees(thd, trx_id0, conds->field_end); + cond1= newx Item_func_history(thd, conds->field_end); + cond2= newx Item_func_trt_trx_sees(thd, trx_id0, conds->field_end); break; default: DBUG_ASSERT(0); @@ -10946,6 +10948,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, j->ref.disable_cache= FALSE; j->ref.null_ref_part= NO_REF_PART; j->ref.const_ref_part_map= 0; + j->ref.uses_splitting= FALSE; keyuse=org_keyuse; store_key **ref_key= j->ref.key_copy; @@ -10994,6 +10997,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, j->ref.null_rejecting|= (key_part_map)1 << i; keyuse_uses_no_tables= keyuse_uses_no_tables && !keyuse->used_tables; + j->ref.uses_splitting |= (keyuse->validity_ref != NULL); /* We don't want to compute heavy expressions in EXPLAIN, an example would select * from t1 where t1.key=(select thats very heavy); @@ -23625,7 +23629,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, todo: why does JT_REF_OR_NULL mean filesort? We could find another index that satisfies the ordering. I would just set ref_key=MAX_KEY here... */ - if (tab->type == JT_REF_OR_NULL || tab->type == JT_FT) + if (tab->type == JT_REF_OR_NULL || tab->type == JT_FT || + tab->ref.uses_splitting) goto use_filesort; } else if (select && select->quick) // Range found by opt_range diff --git a/sql/sql_select.h b/sql/sql_select.h index bd7c0c361c6..89e0c735450 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -178,6 +178,12 @@ typedef struct st_table_ref */ bool disable_cache; + /* + If true, this ref access was constructed from equalities generated by + LATERAL DERIVED (aka GROUP BY splitting) optimization + */ + bool uses_splitting; + bool tmp_table_index_lookup_init(THD *thd, KEY *tmp_key, Item_iterator &it, bool value, uint skip= 0); bool is_access_triggered(); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 38b3d62d539..cb1ce4b7e05 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1458,7 +1458,7 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild) if (open_normal_and_derived_tables(thd, table_list, MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL, - DT_INIT | DT_PREPARE | DT_CREATE)) + DT_INIT | DT_PREPARE)) DBUG_VOID_RETURN; table= table_list->table; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 27ca90cd35b..209c799dc59 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -6091,11 +6091,18 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, /* Ensure that we have an exclusive lock on target table if we are creating non-temporary table. + If we're creating non-temporary table, then either + - there is an exclusive lock on the table + or + - there was CREATE IF EXIST, and the table was not created + (it existed), and was previously locked */ DBUG_ASSERT((create_info->tmp_table()) || thd->mdl_context.is_lock_owner(MDL_key::TABLE, table->db.str, table->table_name.str, - MDL_EXCLUSIVE)); + MDL_EXCLUSIVE) || + (thd->locked_tables_mode && pos_in_locked_tables && + create_info->if_not_exists())); } DEBUG_SYNC(thd, "create_table_like_before_binlog"); @@ -8213,6 +8220,7 @@ static bool mysql_inplace_alter_table(THD *thd, { goto rollback; } + DEBUG_SYNC(thd, "alter_table_inplace_after_commit"); } /* Notify the engine that the table definition has changed */ diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 07dd3b1f6ca..b55bbc7ffac 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -208,7 +208,7 @@ void udf_init() DBUG_PRINT("info",("init udf record")); LEX_CSTRING name; name.str=get_field(&mem, table->field[0]); - name.length = (uint) strlen(name.str); + name.length = (uint) safe_strlen(name.str); char *dl_name= get_field(&mem, table->field[2]); bool new_dl=0; Item_udftype udftype=UDFTYPE_FUNCTION; @@ -222,12 +222,12 @@ void udf_init() On windows we must check both FN_LIBCHAR and '/'. */ - if (check_valid_path(dl_name, strlen(dl_name)) || + if (!name.str || !dl_name || check_valid_path(dl_name, strlen(dl_name)) || check_string_char_length(&name, 0, NAME_CHAR_LEN, system_charset_info, 1)) { sql_print_error("Invalid row in mysql.func table for function '%.64s'", - name.str); + safe_str(name.str)); continue; } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 8ea73439480..578a05d18ae 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1712,8 +1712,9 @@ bool Multiupdate_prelocking_strategy::handle_end(THD *thd) call in setup_tables()). */ - if (setup_tables(thd, &select_lex->context, &select_lex->top_join_list, - table_list, select_lex->leaf_tables, FALSE, TRUE)) + if (setup_tables_and_check_access(thd, &select_lex->context, + &select_lex->top_join_list, table_list, select_lex->leaf_tables, + FALSE, UPDATE_ACL, SELECT_ACL, TRUE)) DBUG_RETURN(1); List<Item> *fields= &lex->first_select_lex()->item_list; |