mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
Merge 10.0 to galera-10.0
This commit is contained in:
352
sql/sql_class.cc
352
sql/sql_class.cc
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Copyright (c) 2000, 2012, Oracle and/or its affiliates.
|
||||
Copyright (c) 2008, 2013, Monty Program Ab
|
||||
Copyright (c) 2000, 2013, Oracle and/or its affiliates.
|
||||
Copyright (c) 2008, 2013, Monty Program Ab.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -63,6 +63,7 @@
|
||||
#include "debug_sync.h"
|
||||
#include "sql_parse.h" // is_update_query
|
||||
#include "sql_callback.h"
|
||||
#include "lock.h"
|
||||
#ifdef WITH_WSREP
|
||||
#include "wsrep_mysqld.h"
|
||||
#endif
|
||||
@@ -75,6 +76,8 @@
|
||||
char internal_table_name[2]= "*";
|
||||
char empty_c_string[1]= {0}; /* used for not defined db */
|
||||
|
||||
LEX_STRING EMPTY_STR= { (char *) "", 0 };
|
||||
|
||||
const char * const THD::DEFAULT_WHERE= "field list";
|
||||
|
||||
/****************************************************************************
|
||||
@@ -131,6 +134,7 @@ Key::Key(const Key &rhs, MEM_ROOT *mem_root)
|
||||
|
||||
Foreign_key::Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root)
|
||||
:Key(rhs,mem_root),
|
||||
ref_db(rhs.ref_db),
|
||||
ref_table(rhs.ref_table),
|
||||
ref_columns(rhs.ref_columns,mem_root),
|
||||
delete_opt(rhs.delete_opt),
|
||||
@@ -586,7 +590,7 @@ void THD::enter_stage(const PSI_stage_info *new_stage,
|
||||
proc_info= msg;
|
||||
|
||||
#ifdef HAVE_PSI_THREAD_INTERFACE
|
||||
PSI_CALL(set_thread_state)(msg);
|
||||
PSI_THREAD_CALL(set_thread_state)(msg);
|
||||
MYSQL_SET_STAGE(m_current_stage_key, calling_file, calling_line);
|
||||
#endif
|
||||
}
|
||||
@@ -685,7 +689,7 @@ int thd_tx_is_read_only(const THD *thd)
|
||||
extern "C"
|
||||
void thd_inc_row_count(THD *thd)
|
||||
{
|
||||
thd->warning_info->inc_current_row_for_warning();
|
||||
thd->get_stmt_da()->inc_current_row_for_warning();
|
||||
}
|
||||
|
||||
|
||||
@@ -764,7 +768,7 @@ char *thd_security_context(THD *thd, char *buffer, unsigned int length,
|
||||
if (max_query_len < 1)
|
||||
len= thd->query_length();
|
||||
else
|
||||
len= min(thd->query_length(), max_query_len);
|
||||
len= MY_MIN(thd->query_length(), max_query_len);
|
||||
str.append('\n');
|
||||
str.append(thd->query(), len);
|
||||
}
|
||||
@@ -779,7 +783,7 @@ char *thd_security_context(THD *thd, char *buffer, unsigned int length,
|
||||
was reallocated to a larger buffer to be able to fit.
|
||||
*/
|
||||
DBUG_ASSERT(buffer != NULL);
|
||||
length= min(str.length(), length-1);
|
||||
length= MY_MIN(str.length(), length-1);
|
||||
memcpy(buffer, str.c_ptr_quick(), length);
|
||||
/* Make sure that the new string is null terminated */
|
||||
buffer[length]= '\0';
|
||||
@@ -870,11 +874,11 @@ extern "C" wsrep_trx_handle_t* wsrep_thd_trx_handle(THD *thd)
|
||||
return &thd->wsrep_trx_handle;
|
||||
}
|
||||
|
||||
extern "C"void wsrep_thd_LOCK(THD *thd)
|
||||
extern "C" void wsrep_thd_LOCK(THD *thd)
|
||||
{
|
||||
mysql_mutex_lock(&thd->LOCK_wsrep_thd);
|
||||
}
|
||||
extern "C"void wsrep_thd_UNLOCK(THD *thd)
|
||||
extern "C" void wsrep_thd_UNLOCK(THD *thd)
|
||||
{
|
||||
mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
|
||||
}
|
||||
@@ -927,7 +931,7 @@ extern "C" void wsrep_thd_awake(THD* bf_thd, THD *thd, my_bool signal)
|
||||
}
|
||||
}
|
||||
|
||||
extern int
|
||||
extern int
|
||||
wsrep_trx_order_before(void *thd1, void *thd2)
|
||||
{
|
||||
if (((THD*)thd1)->wsrep_trx_seqno < ((THD*)thd2)->wsrep_trx_seqno) {
|
||||
@@ -971,9 +975,9 @@ wsrep_trx_is_aborting(void *thd_ptr)
|
||||
bool Drop_table_error_handler::handle_condition(THD *thd,
|
||||
uint sql_errno,
|
||||
const char* sqlstate,
|
||||
MYSQL_ERROR::enum_warning_level level,
|
||||
Sql_condition::enum_warning_level level,
|
||||
const char* msg,
|
||||
MYSQL_ERROR ** cond_hdl)
|
||||
Sql_condition ** cond_hdl)
|
||||
{
|
||||
*cond_hdl= NULL;
|
||||
return ((sql_errno == EE_DELETE && my_errno == ENOENT) ||
|
||||
@@ -1000,8 +1004,6 @@ THD::THD()
|
||||
stmt_depends_on_first_successful_insert_id_in_prev_stmt(FALSE),
|
||||
m_examined_row_count(0),
|
||||
accessed_rows_and_keys(0),
|
||||
warning_info(&main_warning_info),
|
||||
stmt_da(&main_da),
|
||||
m_statement_psi(NULL),
|
||||
m_idle_psi(NULL),
|
||||
m_server_idle(false),
|
||||
@@ -1026,7 +1028,8 @@ THD::THD()
|
||||
#if defined(ENABLED_DEBUG_SYNC)
|
||||
debug_sync_control(0),
|
||||
#endif /* defined(ENABLED_DEBUG_SYNC) */
|
||||
main_warning_info(0, false, false)
|
||||
main_da(0, false, false),
|
||||
m_stmt_da(&main_da)
|
||||
{
|
||||
ulong tmp;
|
||||
|
||||
@@ -1038,8 +1041,8 @@ THD::THD()
|
||||
THD *old_THR_THD= current_thd;
|
||||
set_current_thd(this);
|
||||
status_var.memory_used= 0;
|
||||
main_da.init();
|
||||
|
||||
main_warning_info.init();
|
||||
/*
|
||||
Pass nominal parameters to init_alloc_root only to ensure that
|
||||
the destructor works OK in case of an error. The main_mem_root
|
||||
@@ -1096,6 +1099,7 @@ THD::THD()
|
||||
mysys_var=0;
|
||||
binlog_evt_union.do_union= FALSE;
|
||||
enable_slow_log= 0;
|
||||
durability_property= HA_REGULAR_DURABILITY;
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
dbug_sentry=THD_SENTRY_MAGIC;
|
||||
@@ -1229,9 +1233,9 @@ void THD::push_internal_handler(Internal_error_handler *handler)
|
||||
|
||||
bool THD::handle_condition(uint sql_errno,
|
||||
const char* sqlstate,
|
||||
MYSQL_ERROR::enum_warning_level level,
|
||||
Sql_condition::enum_warning_level level,
|
||||
const char* msg,
|
||||
MYSQL_ERROR ** cond_hdl)
|
||||
Sql_condition ** cond_hdl)
|
||||
{
|
||||
if (!m_internal_handler)
|
||||
{
|
||||
@@ -1268,7 +1272,7 @@ void THD::raise_error(uint sql_errno)
|
||||
const char* msg= ER(sql_errno);
|
||||
(void) raise_condition(sql_errno,
|
||||
NULL,
|
||||
MYSQL_ERROR::WARN_LEVEL_ERROR,
|
||||
Sql_condition::WARN_LEVEL_ERROR,
|
||||
msg);
|
||||
}
|
||||
|
||||
@@ -1284,7 +1288,7 @@ void THD::raise_error_printf(uint sql_errno, ...)
|
||||
va_end(args);
|
||||
(void) raise_condition(sql_errno,
|
||||
NULL,
|
||||
MYSQL_ERROR::WARN_LEVEL_ERROR,
|
||||
Sql_condition::WARN_LEVEL_ERROR,
|
||||
ebuff);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
@@ -1294,7 +1298,7 @@ void THD::raise_warning(uint sql_errno)
|
||||
const char* msg= ER(sql_errno);
|
||||
(void) raise_condition(sql_errno,
|
||||
NULL,
|
||||
MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
Sql_condition::WARN_LEVEL_WARN,
|
||||
msg);
|
||||
}
|
||||
|
||||
@@ -1310,7 +1314,7 @@ void THD::raise_warning_printf(uint sql_errno, ...)
|
||||
va_end(args);
|
||||
(void) raise_condition(sql_errno,
|
||||
NULL,
|
||||
MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
Sql_condition::WARN_LEVEL_WARN,
|
||||
ebuff);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
@@ -1324,7 +1328,7 @@ void THD::raise_note(uint sql_errno)
|
||||
const char* msg= ER(sql_errno);
|
||||
(void) raise_condition(sql_errno,
|
||||
NULL,
|
||||
MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||
Sql_condition::WARN_LEVEL_NOTE,
|
||||
msg);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
@@ -1343,24 +1347,25 @@ void THD::raise_note_printf(uint sql_errno, ...)
|
||||
va_end(args);
|
||||
(void) raise_condition(sql_errno,
|
||||
NULL,
|
||||
MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||
Sql_condition::WARN_LEVEL_NOTE,
|
||||
ebuff);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
MYSQL_ERROR* THD::raise_condition(uint sql_errno,
|
||||
Sql_condition* THD::raise_condition(uint sql_errno,
|
||||
const char* sqlstate,
|
||||
MYSQL_ERROR::enum_warning_level level,
|
||||
Sql_condition::enum_warning_level level,
|
||||
const char* msg)
|
||||
{
|
||||
MYSQL_ERROR *cond= NULL;
|
||||
Diagnostics_area *da= get_stmt_da();
|
||||
Sql_condition *cond= NULL;
|
||||
DBUG_ENTER("THD::raise_condition");
|
||||
|
||||
if (!(variables.option_bits & OPTION_SQL_NOTES) &&
|
||||
(level == MYSQL_ERROR::WARN_LEVEL_NOTE))
|
||||
(level == Sql_condition::WARN_LEVEL_NOTE))
|
||||
DBUG_RETURN(NULL);
|
||||
|
||||
warning_info->opt_clear_warning_info(query_id);
|
||||
da->opt_clear_warning_info(query_id);
|
||||
|
||||
/*
|
||||
TODO: replace by DBUG_ASSERT(sql_errno != 0) once all bugs similar to
|
||||
@@ -1374,24 +1379,24 @@ MYSQL_ERROR* THD::raise_condition(uint sql_errno,
|
||||
if (sqlstate == NULL)
|
||||
sqlstate= mysql_errno_to_sqlstate(sql_errno);
|
||||
|
||||
if ((level == MYSQL_ERROR::WARN_LEVEL_WARN) &&
|
||||
if ((level == Sql_condition::WARN_LEVEL_WARN) &&
|
||||
really_abort_on_warning())
|
||||
{
|
||||
/*
|
||||
FIXME:
|
||||
push_warning and strict SQL_MODE case.
|
||||
*/
|
||||
level= MYSQL_ERROR::WARN_LEVEL_ERROR;
|
||||
level= Sql_condition::WARN_LEVEL_ERROR;
|
||||
killed= KILL_BAD_DATA;
|
||||
}
|
||||
|
||||
switch (level)
|
||||
{
|
||||
case MYSQL_ERROR::WARN_LEVEL_NOTE:
|
||||
case MYSQL_ERROR::WARN_LEVEL_WARN:
|
||||
case Sql_condition::WARN_LEVEL_NOTE:
|
||||
case Sql_condition::WARN_LEVEL_WARN:
|
||||
got_warning= 1;
|
||||
break;
|
||||
case MYSQL_ERROR::WARN_LEVEL_ERROR:
|
||||
case Sql_condition::WARN_LEVEL_ERROR:
|
||||
break;
|
||||
default:
|
||||
DBUG_ASSERT(FALSE);
|
||||
@@ -1400,14 +1405,14 @@ MYSQL_ERROR* THD::raise_condition(uint sql_errno,
|
||||
if (handle_condition(sql_errno, sqlstate, level, msg, &cond))
|
||||
DBUG_RETURN(cond);
|
||||
|
||||
if (level == MYSQL_ERROR::WARN_LEVEL_ERROR)
|
||||
if (level == Sql_condition::WARN_LEVEL_ERROR)
|
||||
{
|
||||
is_slave_error= 1; // needed to catch query errors during replication
|
||||
|
||||
if (! stmt_da->is_error())
|
||||
if (!da->is_error())
|
||||
{
|
||||
set_row_count_func(-1);
|
||||
stmt_da->set_error_status(this, sql_errno, msg, sqlstate);
|
||||
da->set_error_status(sql_errno, msg, sqlstate, cond);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1421,7 +1426,7 @@ MYSQL_ERROR* THD::raise_condition(uint sql_errno,
|
||||
if (!(is_fatal_error && (sql_errno == EE_OUTOFMEMORY ||
|
||||
sql_errno == ER_OUTOFMEMORY)))
|
||||
{
|
||||
cond= warning_info->push_warning(this, sql_errno, sqlstate, level, msg);
|
||||
cond= da->push_warning(this, sql_errno, sqlstate, level, msg);
|
||||
}
|
||||
DBUG_RETURN(cond);
|
||||
}
|
||||
@@ -1534,6 +1539,7 @@ void THD::init(void)
|
||||
tx_read_only= variables.tx_read_only;
|
||||
update_charset();
|
||||
reset_current_stmt_binlog_format_row();
|
||||
reset_binlog_local_stmt_filter();
|
||||
set_status_var_init();
|
||||
bzero((char *) &org_status_var, sizeof(org_status_var));
|
||||
#ifdef WITH_WSREP
|
||||
@@ -1682,6 +1688,8 @@ void THD::cleanup(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
mysql_ha_cleanup(this);
|
||||
|
||||
close_temporary_tables(this);
|
||||
|
||||
transaction.xid_state.xa_state= XA_NOTR;
|
||||
@@ -1689,7 +1697,6 @@ void THD::cleanup(void)
|
||||
xid_cache_delete(&transaction.xid_state);
|
||||
|
||||
locked_tables_list.unlock_locked_tables(this);
|
||||
mysql_ha_cleanup(this);
|
||||
|
||||
DBUG_ASSERT(open_tables == NULL);
|
||||
/*
|
||||
@@ -1745,7 +1752,6 @@ THD::~THD()
|
||||
|
||||
/* Ensure that no one is using THD */
|
||||
mysql_mutex_lock(&LOCK_thd_data);
|
||||
mysys_var=0; // Safety (shouldn't be needed)
|
||||
mysql_mutex_unlock(&LOCK_thd_data);
|
||||
|
||||
#ifdef WITH_WSREP
|
||||
@@ -1770,7 +1776,6 @@ THD::~THD()
|
||||
mysql_audit_release(this);
|
||||
plugin_thdvar_cleanup(this);
|
||||
|
||||
DBUG_PRINT("info", ("freeing security context"));
|
||||
main_security_ctx.destroy();
|
||||
my_free(db);
|
||||
db= NULL;
|
||||
@@ -1794,12 +1799,14 @@ THD::~THD()
|
||||
#endif
|
||||
|
||||
free_root(&main_mem_root, MYF(0));
|
||||
main_warning_info.free_memory();
|
||||
main_da.free_memory();
|
||||
if (status_var.memory_used != 0)
|
||||
{
|
||||
DBUG_PRINT("error", ("memory_used: %lld", status_var.memory_used));
|
||||
SAFEMALLOC_REPORT_MEMORY(my_thread_dbug_id());
|
||||
#ifdef ENABLE_BEFORE_END_OF_MERGE_QQ
|
||||
DBUG_ASSERT(status_var.memory_used == 0); // Ensure everything is freed
|
||||
#endif
|
||||
}
|
||||
|
||||
set_current_thd(orig_thd);
|
||||
@@ -1990,8 +1997,8 @@ void THD::awake(killed_state state_to_set)
|
||||
mysql_mutex_unlock(mysys_var->current_mutex);
|
||||
break;
|
||||
}
|
||||
my_sleep(1000000L / WAIT_FOR_KILL_TRY_TIMES);
|
||||
}
|
||||
my_sleep(1000000L / WAIT_FOR_KILL_TRY_TIMES);
|
||||
}
|
||||
mysql_mutex_unlock(&mysys_var->mutex);
|
||||
}
|
||||
@@ -2032,6 +2039,46 @@ void THD::disconnect()
|
||||
}
|
||||
|
||||
|
||||
bool THD::notify_shared_lock(MDL_context_owner *ctx_in_use,
|
||||
bool needs_thr_lock_abort)
|
||||
{
|
||||
THD *in_use= ctx_in_use->get_thd();
|
||||
bool signalled= FALSE;
|
||||
|
||||
if ((in_use->system_thread & SYSTEM_THREAD_DELAYED_INSERT) &&
|
||||
!in_use->killed)
|
||||
{
|
||||
in_use->killed= KILL_CONNECTION;
|
||||
mysql_mutex_lock(&in_use->mysys_var->mutex);
|
||||
if (in_use->mysys_var->current_cond)
|
||||
mysql_cond_broadcast(in_use->mysys_var->current_cond);
|
||||
mysql_mutex_unlock(&in_use->mysys_var->mutex);
|
||||
signalled= TRUE;
|
||||
}
|
||||
|
||||
if (needs_thr_lock_abort)
|
||||
{
|
||||
mysql_mutex_lock(&in_use->LOCK_thd_data);
|
||||
for (TABLE *thd_table= in_use->open_tables;
|
||||
thd_table ;
|
||||
thd_table= thd_table->next)
|
||||
{
|
||||
/*
|
||||
Check for TABLE::needs_reopen() is needed since in some places we call
|
||||
handler::close() for table instance (and set TABLE::db_stat to 0)
|
||||
and do not remove such instances from the THD::open_tables
|
||||
for some time, during which other thread can see those instances
|
||||
(e.g. see partitioning code).
|
||||
*/
|
||||
if (!thd_table->needs_reopen())
|
||||
signalled|= mysql_lock_abort_for_thread(this, thd_table);
|
||||
}
|
||||
mysql_mutex_unlock(&in_use->LOCK_thd_data);
|
||||
}
|
||||
return signalled;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Get error number for killed state
|
||||
Note that the error message can't have any parameters.
|
||||
@@ -2182,6 +2229,14 @@ void THD::cleanup_after_query()
|
||||
auto_inc_intervals_forced.empty();
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
Forget the binlog stmt filter for the next query.
|
||||
There are some code paths that:
|
||||
- do not call THD::decide_logging_format()
|
||||
- do call THD::binlog_query(),
|
||||
making this reset necessary.
|
||||
*/
|
||||
reset_binlog_local_stmt_filter();
|
||||
if (first_successful_insert_id_in_cur_stmt > 0)
|
||||
{
|
||||
/* set what LAST_INSERT_ID() will return */
|
||||
@@ -2902,7 +2957,7 @@ select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
|
||||
|
||||
Non-ASCII separator arguments are not fully supported
|
||||
*/
|
||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED,
|
||||
ER(WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED));
|
||||
}
|
||||
@@ -2933,7 +2988,7 @@ select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
|
||||
(exchange->opt_enclosed && non_string_results &&
|
||||
field_term_length && strchr(NUMERIC_CHARS, field_term_char)))
|
||||
{
|
||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
ER_AMBIGUOUS_FIELD_TERM, ER(ER_AMBIGUOUS_FIELD_TERM));
|
||||
is_ambiguous_field_term= TRUE;
|
||||
}
|
||||
@@ -3016,7 +3071,7 @@ int select_export::send_data(List<Item> &items)
|
||||
convert_to_printable(printable_buff, sizeof(printable_buff),
|
||||
error_pos, res->ptr() + res->length() - error_pos,
|
||||
res->charset(), 6);
|
||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
|
||||
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
|
||||
"string", printable_buff,
|
||||
@@ -3027,7 +3082,7 @@ int select_export::send_data(List<Item> &items)
|
||||
/*
|
||||
result is longer than UINT_MAX32 and doesn't fit into String
|
||||
*/
|
||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
WARN_DATA_TRUNCATED, ER(WARN_DATA_TRUNCATED),
|
||||
item->full_name(), static_cast<long>(row_count));
|
||||
}
|
||||
@@ -3062,7 +3117,7 @@ int select_export::send_data(List<Item> &items)
|
||||
else
|
||||
{
|
||||
if (fixed_row_size)
|
||||
used_length=min(res->length(),item->max_length);
|
||||
used_length=MY_MIN(res->length(),item->max_length);
|
||||
else
|
||||
used_length=res->length();
|
||||
if ((result_type == STRING_RESULT || is_unsafe_field_sep) &&
|
||||
@@ -3803,7 +3858,7 @@ int select_dumpvar::send_data(List<Item> &items)
|
||||
bool select_dumpvar::send_eof()
|
||||
{
|
||||
if (! row_count)
|
||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA));
|
||||
/*
|
||||
Don't send EOF if we're in error condition (which implies we've already
|
||||
@@ -3974,6 +4029,7 @@ void Security_context::init()
|
||||
|
||||
void Security_context::destroy()
|
||||
{
|
||||
DBUG_PRINT("info", ("freeing security context"));
|
||||
// If not pointer to constant
|
||||
if (host != my_localhost)
|
||||
{
|
||||
@@ -4207,7 +4263,7 @@ static void thd_send_progress(THD *thd)
|
||||
ulonglong report_time= my_interval_timer();
|
||||
if (report_time > thd->progress.next_report_time)
|
||||
{
|
||||
uint seconds_to_next= max(thd->variables.progress_report_time,
|
||||
uint seconds_to_next= MY_MAX(thd->variables.progress_report_time,
|
||||
global_system_variables.progress_report_time);
|
||||
if (seconds_to_next == 0) // Turned off
|
||||
seconds_to_next= 1; // Check again after 1 second
|
||||
@@ -4398,6 +4454,41 @@ extern "C" bool thd_sqlcom_can_generate_row_events(const MYSQL_THD thd)
|
||||
}
|
||||
|
||||
|
||||
extern "C" enum durability_properties thd_get_durability_property(const MYSQL_THD thd)
|
||||
{
|
||||
enum durability_properties ret= HA_REGULAR_DURABILITY;
|
||||
|
||||
if (thd != NULL)
|
||||
ret= thd->durability_property;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Get the auto_increment_offset auto_increment_increment.
|
||||
Needed by InnoDB.
|
||||
@param thd Thread object
|
||||
@param off auto_increment_offset
|
||||
@param inc auto_increment_increment */
|
||||
extern "C" void thd_get_autoinc(const MYSQL_THD thd, ulong* off, ulong* inc)
|
||||
{
|
||||
*off = thd->variables.auto_increment_offset;
|
||||
*inc = thd->variables.auto_increment_increment;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Is strict sql_mode set.
|
||||
Needed by InnoDB.
|
||||
@param thd Thread object
|
||||
@return True if sql_mode has strict mode (all or trans).
|
||||
@retval true sql_mode has strict mode (all or trans).
|
||||
@retval false sql_mode has not strict mode (all or trans).
|
||||
*/
|
||||
extern "C" bool thd_is_strict_mode(const MYSQL_THD thd)
|
||||
{
|
||||
return thd->is_strict_mode();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Interface for MySQL Server, plugins and storage engines to report
|
||||
@@ -4633,7 +4724,7 @@ void THD::inc_status_created_tmp_disk_tables()
|
||||
{
|
||||
status_var_increment(status_var.created_tmp_disk_tables_);
|
||||
#ifdef HAVE_PSI_STATEMENT_INTERFACE
|
||||
PSI_CALL(inc_statement_created_tmp_disk_tables)(m_statement_psi, 1);
|
||||
PSI_STATEMENT_CALL(inc_statement_created_tmp_disk_tables)(m_statement_psi, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -4641,7 +4732,7 @@ void THD::inc_status_created_tmp_tables()
|
||||
{
|
||||
status_var_increment(status_var.created_tmp_tables_);
|
||||
#ifdef HAVE_PSI_STATEMENT_INTERFACE
|
||||
PSI_CALL(inc_statement_created_tmp_tables)(m_statement_psi, 1);
|
||||
PSI_STATEMENT_CALL(inc_statement_created_tmp_tables)(m_statement_psi, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -4649,7 +4740,7 @@ void THD::inc_status_select_full_join()
|
||||
{
|
||||
status_var_increment(status_var.select_full_join_count_);
|
||||
#ifdef HAVE_PSI_STATEMENT_INTERFACE
|
||||
PSI_CALL(inc_statement_select_full_join)(m_statement_psi, 1);
|
||||
PSI_STATEMENT_CALL(inc_statement_select_full_join)(m_statement_psi, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -4657,7 +4748,7 @@ void THD::inc_status_select_full_range_join()
|
||||
{
|
||||
status_var_increment(status_var.select_full_range_join_count_);
|
||||
#ifdef HAVE_PSI_STATEMENT_INTERFACE
|
||||
PSI_CALL(inc_statement_select_full_range_join)(m_statement_psi, 1);
|
||||
PSI_STATEMENT_CALL(inc_statement_select_full_range_join)(m_statement_psi, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -4665,7 +4756,7 @@ void THD::inc_status_select_range()
|
||||
{
|
||||
status_var_increment(status_var.select_range_count_);
|
||||
#ifdef HAVE_PSI_STATEMENT_INTERFACE
|
||||
PSI_CALL(inc_statement_select_range)(m_statement_psi, 1);
|
||||
PSI_STATEMENT_CALL(inc_statement_select_range)(m_statement_psi, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -4673,7 +4764,7 @@ void THD::inc_status_select_range_check()
|
||||
{
|
||||
status_var_increment(status_var.select_range_check_count_);
|
||||
#ifdef HAVE_PSI_STATEMENT_INTERFACE
|
||||
PSI_CALL(inc_statement_select_range_check)(m_statement_psi, 1);
|
||||
PSI_STATEMENT_CALL(inc_statement_select_range_check)(m_statement_psi, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -4681,7 +4772,7 @@ void THD::inc_status_select_scan()
|
||||
{
|
||||
status_var_increment(status_var.select_scan_count_);
|
||||
#ifdef HAVE_PSI_STATEMENT_INTERFACE
|
||||
PSI_CALL(inc_statement_select_scan)(m_statement_psi, 1);
|
||||
PSI_STATEMENT_CALL(inc_statement_select_scan)(m_statement_psi, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -4689,7 +4780,7 @@ void THD::inc_status_sort_merge_passes()
|
||||
{
|
||||
status_var_increment(status_var.filesort_merge_passes_);
|
||||
#ifdef HAVE_PSI_STATEMENT_INTERFACE
|
||||
PSI_CALL(inc_statement_sort_merge_passes)(m_statement_psi, 1);
|
||||
PSI_STATEMENT_CALL(inc_statement_sort_merge_passes)(m_statement_psi, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -4697,7 +4788,7 @@ void THD::inc_status_sort_range()
|
||||
{
|
||||
status_var_increment(status_var.filesort_range_count_);
|
||||
#ifdef HAVE_PSI_STATEMENT_INTERFACE
|
||||
PSI_CALL(inc_statement_sort_range)(m_statement_psi, 1);
|
||||
PSI_STATEMENT_CALL(inc_statement_sort_range)(m_statement_psi, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -4705,7 +4796,7 @@ void THD::inc_status_sort_rows(ha_rows count)
|
||||
{
|
||||
statistic_add(status_var.filesort_rows_, count, &LOCK_status);
|
||||
#ifdef HAVE_PSI_STATEMENT_INTERFACE
|
||||
PSI_CALL(inc_statement_sort_rows)(m_statement_psi, count);
|
||||
PSI_STATEMENT_CALL(inc_statement_sort_rows)(m_statement_psi, count);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -4713,7 +4804,7 @@ void THD::inc_status_sort_scan()
|
||||
{
|
||||
status_var_increment(status_var.filesort_scan_count_);
|
||||
#ifdef HAVE_PSI_STATEMENT_INTERFACE
|
||||
PSI_CALL(inc_statement_sort_scan)(m_statement_psi, 1);
|
||||
PSI_STATEMENT_CALL(inc_statement_sort_scan)(m_statement_psi, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -4721,7 +4812,7 @@ void THD::set_status_no_index_used()
|
||||
{
|
||||
server_status|= SERVER_QUERY_NO_INDEX_USED;
|
||||
#ifdef HAVE_PSI_STATEMENT_INTERFACE
|
||||
PSI_CALL(set_statement_no_index_used)(m_statement_psi);
|
||||
PSI_STATEMENT_CALL(set_statement_no_index_used)(m_statement_psi);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -4729,7 +4820,7 @@ void THD::set_status_no_good_index_used()
|
||||
{
|
||||
server_status|= SERVER_QUERY_NO_GOOD_INDEX_USED;
|
||||
#ifdef HAVE_PSI_STATEMENT_INTERFACE
|
||||
PSI_CALL(set_statement_no_good_index_used)(m_statement_psi);
|
||||
PSI_STATEMENT_CALL(set_statement_no_good_index_used)(m_statement_psi);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -4737,7 +4828,7 @@ void THD::set_command(enum enum_server_command command)
|
||||
{
|
||||
m_command= command;
|
||||
#ifdef HAVE_PSI_THREAD_INTERFACE
|
||||
PSI_CALL(set_thread_command)(m_command);
|
||||
PSI_STATEMENT_CALL(set_thread_command)(m_command);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -4750,7 +4841,7 @@ void THD::set_query(const CSET_STRING &string_arg)
|
||||
mysql_mutex_unlock(&LOCK_thd_data);
|
||||
|
||||
#ifdef HAVE_PSI_THREAD_INTERFACE
|
||||
PSI_CALL(set_thread_info)(query(), query_length());
|
||||
PSI_THREAD_CALL(set_thread_info)(query(), query_length());
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -5063,6 +5154,8 @@ int THD::decide_logging_format(TABLE_LIST *tables)
|
||||
DBUG_PRINT("info", ("lex->get_stmt_unsafe_flags(): 0x%x",
|
||||
lex->get_stmt_unsafe_flags()));
|
||||
|
||||
reset_binlog_local_stmt_filter();
|
||||
|
||||
/*
|
||||
We should not decide logging format if the binlog is closed or
|
||||
binlogging is off, or if the statement is filtered out from the
|
||||
@@ -5105,6 +5198,28 @@ int THD::decide_logging_format(TABLE_LIST *tables)
|
||||
A pointer to a previous table that was accessed.
|
||||
*/
|
||||
TABLE* prev_access_table= NULL;
|
||||
/**
|
||||
The number of tables used in the current statement,
|
||||
that should be replicated.
|
||||
*/
|
||||
uint replicated_tables_count= 0;
|
||||
/**
|
||||
The number of tables written to in the current statement,
|
||||
that should not be replicated.
|
||||
A table should not be replicated when it is considered
|
||||
'local' to a MySQL instance.
|
||||
Currently, these tables are:
|
||||
- mysql.slow_log
|
||||
- mysql.general_log
|
||||
- mysql.slave_relay_log_info
|
||||
- mysql.slave_master_info
|
||||
- mysql.slave_worker_info
|
||||
- performance_schema.*
|
||||
- TODO: information_schema.*
|
||||
In practice, from this list, only performance_schema.* tables
|
||||
are written to by user queries.
|
||||
*/
|
||||
uint non_replicated_tables_count= 0;
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
{
|
||||
@@ -5127,14 +5242,38 @@ int THD::decide_logging_format(TABLE_LIST *tables)
|
||||
if (table->placeholder())
|
||||
continue;
|
||||
|
||||
if (table->table->s->table_category == TABLE_CATEGORY_PERFORMANCE ||
|
||||
table->table->s->table_category == TABLE_CATEGORY_LOG)
|
||||
lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_TABLE);
|
||||
|
||||
handler::Table_flags const flags= table->table->file->ha_table_flags();
|
||||
|
||||
DBUG_PRINT("info", ("table: %s; ha_table_flags: 0x%llx",
|
||||
table->table_name, flags));
|
||||
|
||||
if (table->table->no_replicate && !table->table->s->is_gtid_slave_pos)
|
||||
{
|
||||
/*
|
||||
The statement uses a table that is not replicated.
|
||||
The following properties about the table:
|
||||
- persistent / transient
|
||||
- transactional / non transactional
|
||||
- temporary / permanent
|
||||
- read or write
|
||||
- multiple engines involved because of this table
|
||||
are not relevant, as this table is completely ignored.
|
||||
Because the statement uses a non replicated table,
|
||||
using STATEMENT format in the binlog is impossible.
|
||||
Either this statement will be discarded entirely,
|
||||
or it will be logged (possibly partially) in ROW format.
|
||||
*/
|
||||
lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_TABLE);
|
||||
|
||||
if (table->lock_type >= TL_WRITE_ALLOW_WRITE)
|
||||
{
|
||||
non_replicated_tables_count++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
replicated_tables_count++;
|
||||
|
||||
if (table->lock_type >= TL_WRITE_ALLOW_WRITE)
|
||||
{
|
||||
if (prev_write_table && prev_write_table->file->ht !=
|
||||
@@ -5161,7 +5300,7 @@ int THD::decide_logging_format(TABLE_LIST *tables)
|
||||
|
||||
if (lex->sql_command != SQLCOM_CREATE_TABLE ||
|
||||
(lex->sql_command == SQLCOM_CREATE_TABLE &&
|
||||
(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)))
|
||||
lex->create_info.tmp_table()))
|
||||
{
|
||||
my_bool trans= table->table->file->has_transactions();
|
||||
|
||||
@@ -5317,6 +5456,30 @@ int THD::decide_logging_format(TABLE_LIST *tables)
|
||||
}
|
||||
}
|
||||
|
||||
if (non_replicated_tables_count > 0)
|
||||
{
|
||||
if ((replicated_tables_count == 0) || ! is_write)
|
||||
{
|
||||
DBUG_PRINT("info", ("decision: no logging, no replicated table affected"));
|
||||
set_binlog_local_stmt_filter();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (! is_current_stmt_binlog_format_row())
|
||||
{
|
||||
my_error((error= ER_BINLOG_STMT_MODE_AND_NO_REPL_TABLES), MYF(0));
|
||||
}
|
||||
else
|
||||
{
|
||||
clear_binlog_local_stmt_filter();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
clear_binlog_local_stmt_filter();
|
||||
}
|
||||
|
||||
if (error) {
|
||||
DBUG_PRINT("info", ("decision: no logging since an error was generated"));
|
||||
DBUG_RETURN(-1);
|
||||
@@ -5324,6 +5487,46 @@ int THD::decide_logging_format(TABLE_LIST *tables)
|
||||
DBUG_PRINT("info", ("decision: logging in %s format",
|
||||
is_current_stmt_binlog_format_row() ?
|
||||
"ROW" : "STATEMENT"));
|
||||
|
||||
if (variables.binlog_format == BINLOG_FORMAT_ROW &&
|
||||
(lex->sql_command == SQLCOM_UPDATE ||
|
||||
lex->sql_command == SQLCOM_UPDATE_MULTI ||
|
||||
lex->sql_command == SQLCOM_DELETE ||
|
||||
lex->sql_command == SQLCOM_DELETE_MULTI))
|
||||
{
|
||||
String table_names;
|
||||
/*
|
||||
Generate a warning for UPDATE/DELETE statements that modify a
|
||||
BLACKHOLE table, as row events are not logged in row format.
|
||||
*/
|
||||
for (TABLE_LIST *table= tables; table; table= table->next_global)
|
||||
{
|
||||
if (table->placeholder())
|
||||
continue;
|
||||
if (table->table->file->ht->db_type == DB_TYPE_BLACKHOLE_DB &&
|
||||
table->lock_type >= TL_WRITE_ALLOW_WRITE)
|
||||
{
|
||||
table_names.append(table->table_name);
|
||||
table_names.append(",");
|
||||
}
|
||||
}
|
||||
if (!table_names.is_empty())
|
||||
{
|
||||
bool is_update= (lex->sql_command == SQLCOM_UPDATE ||
|
||||
lex->sql_command == SQLCOM_UPDATE_MULTI);
|
||||
/*
|
||||
Replace the last ',' with '.' for table_names
|
||||
*/
|
||||
table_names.replace(table_names.length()-1, 1, ".", 1);
|
||||
push_warning_printf(this, Sql_condition::WARN_LEVEL_WARN,
|
||||
ER_UNKNOWN_ERROR,
|
||||
"Row events are not logged for %s statements "
|
||||
"that modify BLACKHOLE tables in row format. "
|
||||
"Table(s): '%-.192s'",
|
||||
is_update ? "UPDATE" : "DELETE",
|
||||
table_names.c_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifndef DBUG_OFF
|
||||
else
|
||||
@@ -5918,7 +6121,7 @@ void THD::issue_unsafe_warnings()
|
||||
{
|
||||
if ((unsafe_type_flags & (1 << unsafe_type)) != 0)
|
||||
{
|
||||
push_warning_printf(this, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||
push_warning_printf(this, Sql_condition::WARN_LEVEL_NOTE,
|
||||
ER_BINLOG_UNSAFE_STATEMENT,
|
||||
ER(ER_BINLOG_UNSAFE_STATEMENT),
|
||||
ER(LEX::binlog_stmt_unsafe_errcode[unsafe_type]));
|
||||
@@ -5972,6 +6175,15 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg,
|
||||
#else
|
||||
DBUG_ASSERT(query_arg && mysql_bin_log.is_open());
|
||||
#endif
|
||||
|
||||
if (get_binlog_local_stmt_filter() == BINLOG_FILTER_SET)
|
||||
{
|
||||
/*
|
||||
The current statement is to be ignored, and not written to
|
||||
the binlog. Do not call issue_unsafe_warnings().
|
||||
*/
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
/*
|
||||
If we are not in prelocked mode, mysql_unlock_tables() will be
|
||||
called after this binlog_query(), so we have to flush the pending
|
||||
|
Reference in New Issue
Block a user