summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorNikita Malyavin <nikitamalyavin@gmail.com>2021-05-05 23:03:01 +0300
committerNikita Malyavin <nikitamalyavin@gmail.com>2021-05-05 23:03:01 +0300
commit509e4990af4d99e9d3c790eabe1c1705ae910b55 (patch)
tree02d4ca9409711baef3ec163adc402f2c380df7c8 /sql
parent0cc811c633d1fe5290b10fa49fad0a4b889383fa (diff)
parent4f143a88bcb36e94e9edba8a3c5b4a350dcd9bf9 (diff)
downloadmariadb-git-509e4990af4d99e9d3c790eabe1c1705ae910b55.tar.gz
Merge branch bb-10.3-release into bb-10.4-release
Diffstat (limited to 'sql')
-rw-r--r--sql/field.h5
-rw-r--r--sql/item_create.cc15
-rw-r--r--sql/item_create.h1
-rw-r--r--sql/item_vers.cc16
-rw-r--r--sql/item_vers.h30
-rw-r--r--sql/log_event.cc17
-rw-r--r--sql/log_event.h13
-rw-r--r--sql/sp_head.h2
-rw-r--r--sql/sql_acl.cc6
-rw-r--r--sql/sql_base.cc3
-rw-r--r--sql/sql_class.cc2
-rw-r--r--sql/sql_class.h4
-rw-r--r--sql/sql_derived.cc6
-rw-r--r--sql/sql_insert.cc5
-rw-r--r--sql/sql_lex.cc74
-rw-r--r--sql/sql_lex.h4
-rw-r--r--sql/sql_prepare.cc16
-rw-r--r--sql/sql_repl.cc31
-rw-r--r--sql/sql_select.cc11
-rw-r--r--sql/sql_select.h6
-rw-r--r--sql/sql_show.cc2
-rw-r--r--sql/sql_table.cc10
-rw-r--r--sql/sql_udf.cc6
-rw-r--r--sql/sql_update.cc5
24 files changed, 207 insertions, 83 deletions
diff --git a/sql/field.h b/sql/field.h
index 421d6bddb2d..477c64727b3 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -988,8 +988,9 @@ public:
virtual void reset_fields() {}
const uchar *ptr_in_record(const uchar *record) const
{
- my_ptrdiff_t l_offset= (my_ptrdiff_t) (record - table->record[0]);
- return ptr + l_offset;
+ my_ptrdiff_t l_offset= (my_ptrdiff_t) (ptr - table->record[0]);
+ DBUG_ASSERT(l_offset >= 0 && table->s->rec_buff_length - l_offset > 0);
+ return record + l_offset;
}
virtual int set_default();
diff --git a/sql/item_create.cc b/sql/item_create.cc
index a80781259ca..ffc90e16b8f 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -7584,6 +7584,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 5890e8ad057..bb129a14d40 100644
--- a/sql/item_create.h
+++ b/sql/item_create.h
@@ -199,6 +199,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.cc b/sql/log_event.cc
index 337de3508ed..349e35488e2 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -15143,14 +15143,23 @@ bool copy_event_cache_to_file_and_reinit(IO_CACHE *cache, FILE *file)
}
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-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/log_event.h b/sql/log_event.h
index 49e244f1151..5719bb99a68 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -570,6 +570,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
@@ -5214,12 +5222,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/sp_head.h b/sql/sp_head.h
index 6cf4610c466..500446c5e16 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -109,7 +109,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 96f1b87d5d7..70607a0cf8e 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -2068,7 +2068,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 cc6ecda9327..f4d9272eca1 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -5372,7 +5372,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;
@@ -5430,7 +5429,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 093a94f44f8..0d61a38e918 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -4753,7 +4753,7 @@ TABLE *open_purge_table(THD *thd, const char *db, size_t dblen,
DBUG_ASSERT(thd->open_tables == NULL);
DBUG_ASSERT(thd->locked_tables_mode < LTM_PRELOCKED);
- Open_table_context ot_ctx(thd, 0);
+ Open_table_context ot_ctx(thd, MYSQL_OPEN_IGNORE_FLUSH);
TABLE_LIST *tl= (TABLE_LIST*)thd->alloc(sizeof(TABLE_LIST));
LEX_CSTRING db_name= {db, dblen };
LEX_CSTRING table_name= { tb, tblen };
diff --git a/sql/sql_class.h b/sql/sql_class.h
index eb9ea535862..8edc6225d73 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -3655,10 +3655,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 132872c4a9e..fc01dcdc750 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 c969725bea4..820a305059f 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1820,9 +1820,10 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
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 5937c43c95d..386d179322e 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -788,15 +788,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. */
@@ -805,33 +805,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);
@@ -2234,6 +2224,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.
@@ -2243,28 +2238,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;
@@ -5761,13 +5745,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 466b23b3f94..2389b23e08e 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -4833,8 +4833,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 f0b8fc7309e..8d094a09165 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -1608,7 +1608,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
@@ -1670,7 +1670,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));
@@ -1702,7 +1702,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++))
@@ -1866,7 +1866,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;
@@ -4308,8 +4308,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;
@@ -5141,7 +5143,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 6a6cfb2aa5f..841ff561502 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -33,6 +33,7 @@
#include "semisync_slave.h"
#include "mysys_err.h"
+
enum enum_gtid_until_state {
GTID_UNTIL_NOT_DONE,
GTID_UNTIL_STOP_AFTER_STANDALONE,
@@ -817,7 +818,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
@@ -831,6 +832,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);
@@ -851,18 +854,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 52abaf29d05..12d0a9e824e 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -852,7 +852,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);
@@ -905,7 +906,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);
@@ -10748,6 +10750,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;
@@ -10796,6 +10799,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);
@@ -23266,7 +23270,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 d21d1bcc305..8d65a6183a0 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 6f0c9761b6c..7b5b2c8bf89 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1571,7 +1571,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 0249ae68cc3..8fe1f34256c 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -5839,11 +5839,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");
@@ -7867,6 +7874,7 @@ static bool mysql_inplace_alter_table(THD *thd,
{
goto rollback;
}
+ DEBUG_SYNC(thd, "alter_table_inplace_after_commit");
}
close_all_tables_for_name(thd, table->s,
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index 3f7289fdca2..400a8ae8c30 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -197,7 +197,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;
@@ -211,12 +211,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 41ea52ef3c3..85db99f3a62 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -1710,8 +1710,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;