summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/field.h5
-rw-r--r--sql/log_event.cc17
-rw-r--r--sql/log_event.h13
-rw-r--r--sql/sql_acl.cc6
-rw-r--r--sql/sql_class.cc2
-rw-r--r--sql/sql_insert.cc5
-rw-r--r--sql/sql_lex.cc56
-rw-r--r--sql/sql_lex.h4
-rw-r--r--sql/sql_prepare.cc8
-rw-r--r--sql/sql_repl.cc31
-rw-r--r--sql/sql_table.cc11
-rw-r--r--sql/sql_udf.cc6
-rw-r--r--sql/sql_update.cc5
13 files changed, 119 insertions, 50 deletions
diff --git a/sql/field.h b/sql/field.h
index 1344774c189..a3385736c0a 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -980,8 +980,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/log_event.cc b/sql/log_event.cc
index d072402a00b..cfebdaa3e3c 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -15097,14 +15097,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 8a342cb5cd3..57282fe58ce 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
@@ -5183,12 +5191,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/sql_acl.cc b/sql/sql_acl.cc
index 1cc322092e2..1327d2943b5 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1471,7 +1471,11 @@ static bool validate_password(LEX_USER *user, THD *thd)
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_class.cc b/sql/sql_class.cc
index 51ac3e42cd9..c4905fcabf6 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -4677,7 +4677,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_insert.cc b/sql/sql_insert.cc
index 9db6acf73f8..09d15133e6d 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1798,9 +1798,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 b1c5327d10c..4f90fb28b45 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -766,15 +766,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. */
@@ -783,33 +783,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);
@@ -5448,13 +5438,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 16768e0300f..748e6180642 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -4340,8 +4340,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 9775e99afdd..bce7c6afa17 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -4276,8 +4276,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;
@@ -5159,7 +5161,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 6a95a68864f..389346e389d 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -32,6 +32,7 @@
#include "semisync_master.h"
#include "semisync_slave.h"
+
enum enum_gtid_until_state {
GTID_UNTIL_NOT_DONE,
GTID_UNTIL_STOP_AFTER_STANDALONE,
@@ -813,7 +814,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
@@ -827,6 +828,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);
@@ -847,18 +850,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_table.cc b/sql/sql_table.cc
index 4883fd93782..c70639d71db 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -5818,11 +5818,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");
@@ -7788,6 +7795,8 @@ static bool mysql_inplace_alter_table(THD *thd,
goto rollback;
}
+ DEBUG_SYNC(thd, "alter_table_inplace_after_commit");
+
thd->drop_temporary_table(altered_table, NULL, false);
}
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index d75b1cdedde..d0657cf973e 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -195,7 +195,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;
@@ -209,12 +209,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 c58eb4e193d..eeed815b716 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -1571,8 +1571,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->select_lex.item_list;