summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/backup.cc6
-rw-r--r--sql/handler.cc23
-rw-r--r--sql/log.cc9
-rw-r--r--sql/log_event.cc2
-rw-r--r--sql/mysqld.cc10
-rw-r--r--sql/opt_range.cc20
-rw-r--r--sql/share/errmsg-utf8.txt5
-rw-r--r--sql/sql_class.cc2
-rw-r--r--sql/sql_class.h18
-rw-r--r--sql/sql_delete.cc3
-rw-r--r--sql/sql_parse.cc54
-rw-r--r--sql/sql_prepare.cc4
-rw-r--r--sql/sql_reload.cc10
-rw-r--r--sql/sql_select.cc6
-rw-r--r--sql/sql_show.cc5
-rw-r--r--sql/sql_table.cc23
-rw-r--r--sql/sql_type.cc8
-rw-r--r--sql/sql_udf.cc148
-rw-r--r--sql/sql_udf.h8
-rw-r--r--sql/sql_update.cc2
-rw-r--r--sql/sql_yacc.yy8
-rw-r--r--sql/table.cc3
-rw-r--r--sql/threadpool_common.cc14
-rw-r--r--sql/wsrep_mysqld.h3
-rw-r--r--sql/wsrep_var.cc3
25 files changed, 284 insertions, 113 deletions
diff --git a/sql/backup.cc b/sql/backup.cc
index 02570dfd30d..e89f9a108a7 100644
--- a/sql/backup.cc
+++ b/sql/backup.cc
@@ -378,7 +378,13 @@ bool backup_reset_alter_copy_lock(THD *thd)
bool backup_lock(THD *thd, TABLE_LIST *table)
{
+ /* We should leave the previous table unlocked in case of errors */
backup_unlock(thd);
+ if (thd->locked_tables_mode)
+ {
+ my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
+ return 1;
+ }
table->mdl_request.duration= MDL_EXPLICIT;
if (thd->mdl_context.acquire_lock(&table->mdl_request,
thd->variables.lock_wait_timeout))
diff --git a/sql/handler.cc b/sql/handler.cc
index 302467b4479..c33dcb192d8 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -2316,7 +2316,7 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin,
for (int i=0; i < got; i ++)
{
- my_xid x= IF_WSREP(WSREP_ON && wsrep_is_wsrep_xid(&info->list[i]) ?
+ my_xid x= IF_WSREP(wsrep_is_wsrep_xid(&info->list[i]) ?
wsrep_xid_seqno(&info->list[i]) :
info->list[i].get_my_xid(),
info->list[i].get_my_xid());
@@ -6323,6 +6323,7 @@ extern "C" check_result_t handler_index_cond_check(void* h_arg)
THD *thd= h->table->in_use;
check_result_t res;
+ DEBUG_SYNC(thd, "handler_index_cond_check");
enum thd_kill_levels abort_at= h->has_rollback() ?
THD_ABORT_SOFTLY : THD_ABORT_ASAP;
if (thd_kill_level(thd) > abort_at)
@@ -6356,6 +6357,7 @@ check_result_t handler_rowid_filter_check(void *h_arg)
if (!h->pushed_idx_cond)
{
THD *thd= h->table->in_use;
+ DEBUG_SYNC(thd, "handler_rowid_filter_check");
enum thd_kill_levels abort_at= h->has_transactions() ?
THD_ABORT_SOFTLY : THD_ABORT_ASAP;
if (thd_kill_level(thd) > abort_at)
@@ -8082,6 +8084,8 @@ Vers_parse_info::fix_create_like(Alter_info &alter_info, HA_CREATE_INFO &create_
TABLE_LIST &src_table, TABLE_LIST &table)
{
List_iterator<Create_field> it(alter_info.create_list);
+ List_iterator<Key> key_it(alter_info.key_list);
+ List_iterator<Key_part_spec> kp_it;
Create_field *f, *f_start=NULL, *f_end= NULL;
DBUG_ASSERT(alter_info.create_list.elements > 2);
@@ -8096,6 +8100,23 @@ Vers_parse_info::fix_create_like(Alter_info &alter_info, HA_CREATE_INFO &create_
it.remove();
remove--;
}
+ key_it.rewind();
+ while (Key *key= key_it++)
+ {
+ kp_it.init(key->columns);
+ while (Key_part_spec *kp= kp_it++)
+ {
+ if (0 == lex_string_cmp(system_charset_info, &kp->field_name,
+ &f->field_name))
+ {
+ kp_it.remove();
+ }
+ }
+ if (0 == key->columns.elements)
+ {
+ key_it.remove();
+ }
+ }
}
DBUG_ASSERT(remove == 0);
push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
diff --git a/sql/log.cc b/sql/log.cc
index 60e2bf9d4ab..2dd1a3a45ab 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -601,9 +601,11 @@ bool LOGGER::is_log_table_enabled(uint log_table_type)
{
switch (log_table_type) {
case QUERY_LOG_SLOW:
- return (table_log_handler != NULL) && global_system_variables.sql_log_slow;
+ return (table_log_handler != NULL) && global_system_variables.sql_log_slow
+ && (log_output_options & LOG_TABLE);
case QUERY_LOG_GENERAL:
- return (table_log_handler != NULL) && opt_log ;
+ return (table_log_handler != NULL) && opt_log
+ && (log_output_options & LOG_TABLE);
default:
DBUG_ASSERT(0);
return FALSE; /* make compiler happy */
@@ -10805,7 +10807,8 @@ binlog_checksum_update(MYSQL_THD thd, struct st_mysql_sys_var *var,
}
-static int show_binlog_vars(THD *thd, SHOW_VAR *var, char *buff)
+static int show_binlog_vars(THD *thd, SHOW_VAR *var, void *,
+ system_status_var *status_var, enum_var_type)
{
mysql_bin_log.set_status_variables(thd);
var->type= SHOW_ARRAY;
diff --git a/sql/log_event.cc b/sql/log_event.cc
index d66ece96eba..0388a2b19b1 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -1074,7 +1074,7 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len,
else
DBUG_RETURN(NULL);
#else
- *error= ER(ER_BINLOG_READ_EVENT_CHECKSUM_FAILURE);
+ *error= ER_THD_OR_DEFAULT(current_thd, ER_BINLOG_READ_EVENT_CHECKSUM_FAILURE);
sql_print_error("%s", *error);
DBUG_RETURN(NULL);
#endif
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 6b103c69a69..9834d331474 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -7165,8 +7165,8 @@ show_ssl_get_server_not_after(THD *thd, SHOW_VAR *var, char *buff,
#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
-static int show_default_keycache(THD *thd, SHOW_VAR *var, char *buff,
- enum enum_var_type scope)
+static int show_default_keycache(THD *thd, SHOW_VAR *var, void *buff,
+ system_status_var *, enum_var_type)
{
struct st_data {
KEY_CACHE_STATISTICS stats;
@@ -7199,7 +7199,7 @@ static int show_default_keycache(THD *thd, SHOW_VAR *var, char *buff,
v->name= 0;
- DBUG_ASSERT((char*)(v+1) <= buff + SHOW_VAR_FUNC_BUFF_SIZE);
+ DBUG_ASSERT((char*)(v+1) <= static_cast<char*>(buff) + SHOW_VAR_FUNC_BUFF_SIZE);
#undef set_one_keycache_var
@@ -7223,8 +7223,8 @@ static int show_memory_used(THD *thd, SHOW_VAR *var, char *buff,
#ifndef DBUG_OFF
-static int debug_status_func(THD *thd, SHOW_VAR *var, char *buff,
- enum enum_var_type scope)
+static int debug_status_func(THD *thd, SHOW_VAR *var, void *buff,
+ system_status_var *, enum_var_type)
{
#define add_var(X,Y,Z) \
v->name= X; \
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index c674730d230..c13563f9263 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -1872,6 +1872,9 @@ SEL_ARG::SEL_ARG(SEL_ARG &arg) :Sql_alloc()
next_key_part=arg.next_key_part;
max_part_no= arg.max_part_no;
use_count=1; elements=1;
+ next= 0;
+ if (next_key_part)
+ ++next_key_part->use_count;
}
@@ -9616,9 +9619,15 @@ tree_or(RANGE_OPT_PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2)
}
bool no_imerge_from_ranges= FALSE;
+ SEL_TREE *rt1= tree1;
+ SEL_TREE *rt2= tree2;
/* Build the range part of the tree for the formula (1) */
if (sel_trees_can_be_ored(param, tree1, tree2, &ored_keys))
{
+ if (no_merges1)
+ rt1= new SEL_TREE(tree1, TRUE, param);
+ if (no_merges2)
+ rt2= new SEL_TREE(tree2, TRUE, param);
bool must_be_ored= sel_trees_must_be_ored(param, tree1, tree2, ored_keys);
no_imerge_from_ranges= must_be_ored;
@@ -9676,12 +9685,6 @@ tree_or(RANGE_OPT_PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2)
else if (!no_ranges1 && !no_ranges2 && !no_imerge_from_ranges)
{
/* Build the imerge part of the tree for the formula (1) */
- SEL_TREE *rt1= tree1;
- SEL_TREE *rt2= tree2;
- if (no_merges1)
- rt1= new SEL_TREE(tree1, TRUE, param);
- if (no_merges2)
- rt2= new SEL_TREE(tree2, TRUE, param);
if (!rt1 || !rt2 ||
result->merges.push_back(imerge_from_ranges) ||
imerge_from_ranges->or_sel_tree(param, rt1) ||
@@ -10346,10 +10349,11 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2)
if (!tmp->next_key_part)
{
+ SEL_ARG *key2_next= key2->next;
if (key2->use_count)
{
SEL_ARG *key2_cpy= new SEL_ARG(*key2);
- if (key2_cpy)
+ if (!key2_cpy)
return 0;
key2= key2_cpy;
}
@@ -10370,7 +10374,7 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2)
Move on to next range in key2
*/
key2->increment_use_count(-1); // Free not used tree
- key2=key2->next;
+ key2=key2_next;
continue;
}
else
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 8a60ad707f5..3f3cb7677fc 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -5722,8 +5722,9 @@ ER_SP_RECURSION_LIMIT
eng "Recursive limit %d (as set by the max_sp_recursion_depth variable) was exceeded for routine %.192s"
ger "Rekursionsgrenze %d (durch Variable max_sp_recursion_depth gegeben) wurde für Routine %.192s überschritten"
ER_SP_PROC_TABLE_CORRUPT
- eng "Failed to load routine %-.192s. The table mysql.proc is missing, corrupt, or contains bad data (internal code %d)"
- ger "Routine %-.192s konnte nicht geladen werden. Die Tabelle mysql.proc fehlt, ist beschädigt, oder enthält fehlerhaften Daten (interner Code: %d)"
+ eng "Failed to load routine %-.192s (internal code %d). For more details, run SHOW WARNINGS"
+ ger "Routine %-.192s (interner Code %d) konnte nicht geladen werden. Weitere Einzelheiten erhalten Sie, wenn Sie SHOW WARNINGS ausführen"
+ ukr "Невдала спроба завантажити процедуру %-.192s (внутрішний код %d). Для отримання детальної інформації використовуйте SHOW WARNINGS"
ER_SP_WRONG_NAME 42000
eng "Incorrect routine name '%-.192s'"
ger "Ungültiger Routinenname '%-.192s'"
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index b94630274d5..6011dbbc6dd 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -2589,7 +2589,7 @@ void THD::give_protection_error()
my_error(ER_BACKUP_LOCK_IS_ACTIVE, MYF(0));
else
{
- DBUG_ASSERT(global_read_lock.is_acquired());
+ DBUG_ASSERT(global_read_lock.is_acquired() || mdl_backup_lock);
my_error(ER_CANT_UPDATE_WITH_READLOCK, MYF(0));
}
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index e20366e578b..87773b8338a 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -284,8 +284,9 @@ class Key_part_spec :public Sql_alloc {
public:
LEX_CSTRING field_name;
uint length;
- Key_part_spec(const LEX_CSTRING *name, uint len)
- : field_name(*name), length(len)
+ bool generated;
+ Key_part_spec(const LEX_CSTRING *name, uint len, bool gen= false)
+ : field_name(*name), length(len), generated(gen)
{}
bool operator==(const Key_part_spec& other) const;
/**
@@ -3774,10 +3775,17 @@ public:
/* Commit both statement and full transaction */
int commit_whole_transaction_and_close_tables();
void give_protection_error();
+ /*
+ Give an error if any of the following is true for this connection
+ - BACKUP STAGE is active
+ - FLUSH TABLE WITH READ LOCK is active
+ - BACKUP LOCK table_name is active
+ */
inline bool has_read_only_protection()
{
if (current_backup_stage == BACKUP_FINISHED &&
- !global_read_lock.is_acquired())
+ !global_read_lock.is_acquired() &&
+ !mdl_backup_lock)
return FALSE;
give_protection_error();
return TRUE;
@@ -6882,11 +6890,11 @@ public:
/**
SP Bulk execution safe
*/
-#define CF_SP_BULK_SAFE (1U << 20)
+#define CF_PS_ARRAY_BINDING_SAFE (1U << 20)
/**
SP Bulk execution optimized
*/
-#define CF_SP_BULK_OPTIMIZED (1U << 21)
+#define CF_PS_ARRAY_BINDING_OPTIMIZED (1U << 21)
/**
If command creates or drops a table
*/
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 7280236e43f..7586b2831ae 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -248,6 +248,7 @@ int update_portion_of_time(THD *thd, TABLE *table,
uint dst_fieldno= lcond ? table->s->period.end_fieldno
: table->s->period.start_fieldno;
+ table->file->store_auto_increment();
store_record(table, record[1]);
if (likely(!res))
res= src->save_in_field(table->field[dst_fieldno], true);
@@ -262,6 +263,8 @@ int update_portion_of_time(THD *thd, TABLE *table,
res= table->triggers->process_triggers(thd, TRG_EVENT_INSERT,
TRG_ACTION_AFTER, true);
restore_record(table, record[1]);
+ if (res)
+ table->file->restore_auto_increment();
if (likely(!res) && lcond && rcond)
res= table->period_make_insert(period_conds.end.item,
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index c8fad45acac..3eb28d960b3 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -579,19 +579,21 @@ void init_update_queries(void)
CF_CAN_GENERATE_ROW_EVENTS |
CF_OPTIMIZER_TRACE |
CF_CAN_BE_EXPLAINED |
- CF_UPDATES_DATA | CF_SP_BULK_SAFE;
+ CF_UPDATES_DATA |
+ CF_PS_ARRAY_BINDING_SAFE;
sql_command_flags[SQLCOM_UPDATE_MULTI]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS |
CF_OPTIMIZER_TRACE |
CF_CAN_BE_EXPLAINED |
- CF_UPDATES_DATA | CF_SP_BULK_SAFE;
+ CF_UPDATES_DATA |
+ CF_PS_ARRAY_BINDING_SAFE;
sql_command_flags[SQLCOM_INSERT]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS |
CF_OPTIMIZER_TRACE |
CF_CAN_BE_EXPLAINED |
CF_INSERTS_DATA |
- CF_SP_BULK_SAFE |
- CF_SP_BULK_OPTIMIZED;
+ CF_PS_ARRAY_BINDING_SAFE |
+ CF_PS_ARRAY_BINDING_OPTIMIZED;
sql_command_flags[SQLCOM_INSERT_SELECT]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS |
CF_OPTIMIZER_TRACE |
@@ -601,7 +603,8 @@ void init_update_queries(void)
CF_CAN_GENERATE_ROW_EVENTS |
CF_OPTIMIZER_TRACE |
CF_CAN_BE_EXPLAINED |
- CF_SP_BULK_SAFE | CF_DELETES_DATA;
+ CF_DELETES_DATA |
+ CF_PS_ARRAY_BINDING_SAFE;
sql_command_flags[SQLCOM_DELETE_MULTI]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS |
CF_OPTIMIZER_TRACE |
@@ -611,8 +614,9 @@ void init_update_queries(void)
CF_CAN_GENERATE_ROW_EVENTS |
CF_OPTIMIZER_TRACE |
CF_CAN_BE_EXPLAINED |
- CF_INSERTS_DATA | CF_SP_BULK_SAFE |
- CF_SP_BULK_OPTIMIZED;
+ CF_INSERTS_DATA |
+ CF_PS_ARRAY_BINDING_SAFE |
+ CF_PS_ARRAY_BINDING_OPTIMIZED;
sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS |
CF_OPTIMIZER_TRACE |
@@ -775,7 +779,7 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_ALTER_SERVER]= CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_DROP_SERVER]= CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_BACKUP]= CF_AUTO_COMMIT_TRANS;
- sql_command_flags[SQLCOM_BACKUP_LOCK]= 0;
+ sql_command_flags[SQLCOM_BACKUP_LOCK]= CF_AUTO_COMMIT_TRANS;
/*
The following statements can deal with temporary tables,
@@ -5080,6 +5084,13 @@ mysql_execute_command(THD *thd)
goto error;
}
+ /* Should not lock tables while BACKUP LOCK is active */
+ if (thd->mdl_backup_lock)
+ {
+ my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
+ goto error;
+ }
+
/*
Here we have to pre-open temporary tables for LOCK TABLES.
@@ -6484,24 +6495,21 @@ drop_routine(THD *thd, LEX *lex)
! lex->spname->m_explicit_name)
{
/* DROP FUNCTION <non qualified name> */
- udf_func *udf = find_udf(lex->spname->m_name.str,
- lex->spname->m_name.length);
- if (udf)
- {
- if (check_access(thd, DELETE_ACL, "mysql", NULL, NULL, 1, 0))
- return 1;
-
- if (!mysql_drop_function(thd, &lex->spname->m_name))
- {
- my_ok(thd);
- return 0;
- }
- my_error(ER_SP_DROP_FAILED, MYF(0),
- "FUNCTION (UDF)", lex->spname->m_name.str);
+ enum drop_udf_result rc= mysql_drop_function(thd, &lex->spname->m_name);
+ switch (rc) {
+ case UDF_DEL_RESULT_DELETED:
+ my_ok(thd);
+ return 0;
+ case UDF_DEL_RESULT_ERROR:
return 1;
+ case UDF_DEL_RESULT_ABSENT:
+ goto absent;
}
- if (lex->spname->m_db.str == NULL)
+ DBUG_ASSERT("wrong return code" == 0);
+absent:
+ // If there was no current database, so it cannot be SP
+ if (!lex->spname->m_db.str)
{
if (lex->if_exists())
{
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 8b801ae7cd9..bb0a399d1ed 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -4368,7 +4368,7 @@ Prepared_statement::execute_bulk_loop(String *expanded_query,
return TRUE;
}
- if (!(sql_command_flags[lex->sql_command] & CF_SP_BULK_SAFE))
+ if (!(sql_command_flags[lex->sql_command] & CF_PS_ARRAY_BINDING_SAFE))
{
DBUG_PRINT("error", ("Command is not supported in bulk execution."));
my_error(ER_UNSUPPORTED_PS, MYF(0));
@@ -4400,7 +4400,7 @@ Prepared_statement::execute_bulk_loop(String *expanded_query,
Here we set parameters for not optimized commands,
optimized commands do it inside thier internal loop.
*/
- if (!(sql_command_flags[lex->sql_command] & CF_SP_BULK_OPTIMIZED))
+ if (!(sql_command_flags[lex->sql_command] & CF_PS_ARRAY_BINDING_OPTIMIZED))
{
if (set_bulk_parameters(TRUE))
{
diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc
index ae5a26e1529..8f87d633d19 100644
--- a/sql/sql_reload.cc
+++ b/sql/sql_reload.cc
@@ -218,6 +218,7 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options,
thd->handler_tables_hash.records ||
thd->ull_hash.records ||
thd->global_read_lock.is_acquired() ||
+ thd->mdl_backup_lock ||
thd->current_backup_stage != BACKUP_FINISHED
);
@@ -530,7 +531,14 @@ bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables)
if (thd->current_backup_stage != BACKUP_FINISHED)
{
my_error(ER_BACKUP_LOCK_IS_ACTIVE, MYF(0));
- return true;
+ goto error;
+ }
+
+ /* Should not flush tables while BACKUP LOCK is active */
+ if (thd->mdl_backup_lock)
+ {
+ my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
+ goto error;
}
if (thd->lex->type & REFRESH_READ_LOCK)
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 22ff3a6e0e3..c54f8902976 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -439,11 +439,14 @@ bool handle_select(THD *thd, LEX *lex, select_result *result,
If LIMIT ROWS EXAMINED interrupted query execution, issue a warning,
continue with normal processing and produce an incomplete query result.
*/
+ bool saved_abort_on_warning= thd->abort_on_warning;
+ thd->abort_on_warning= false;
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_QUERY_EXCEEDED_ROWS_EXAMINED_LIMIT,
ER_THD(thd, ER_QUERY_EXCEEDED_ROWS_EXAMINED_LIMIT),
thd->accessed_rows_and_keys,
thd->lex->limit_rows_examined->val_uint());
+ thd->abort_on_warning= saved_abort_on_warning;
thd->reset_killed();
}
/* Disable LIMIT ROWS EXAMINED after query execution. */
@@ -743,7 +746,7 @@ bool vers_select_conds_t::init_from_sysvar(THD *thd)
void vers_select_conds_t::print(String *str, enum_query_type query_type) const
{
- switch (type) {
+ switch (orig_type) {
case SYSTEM_TIME_UNSPECIFIED:
break;
case SYSTEM_TIME_AS_OF:
@@ -991,6 +994,7 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables)
case SQLCOM_SELECT:
use_sysvar= true;
/* fall through */
+ case SQLCOM_CREATE_TABLE:
case SQLCOM_INSERT_SELECT:
case SQLCOM_REPLACE_SELECT:
case SQLCOM_DELETE_MULTI:
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 1e32e8b2925..794589b234c 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -5251,6 +5251,11 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
free_root(&tmp_mem_root, MY_MARK_BLOCKS_FREE);
}
}
+ if (thd->killed == ABORT_QUERY)
+ {
+ error= 0;
+ goto err;
+ }
}
}
}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 16f4330637d..ec4ec0d26e9 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -3457,10 +3457,9 @@ Key *
mysql_add_invisible_index(THD *thd, List<Key> *key_list,
LEX_CSTRING* field_name, enum Key::Keytype type)
{
- Key *key= NULL;
- key= new (thd->mem_root) Key(type, &null_clex_str, HA_KEY_ALG_UNDEF,
- false, DDL_options(DDL_options::OPT_NONE));
- key->columns.push_back(new(thd->mem_root) Key_part_spec(field_name, 0),
+ Key *key= new (thd->mem_root) Key(type, &null_clex_str, HA_KEY_ALG_UNDEF,
+ false, DDL_options(DDL_options::OPT_NONE));
+ key->columns.push_back(new(thd->mem_root) Key_part_spec(field_name, 0, true),
thd->mem_root);
key_list->push_back(key, thd->mem_root);
return key;
@@ -4034,7 +4033,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
/*
Either field is not present or field visibility is > INVISIBLE_USER
*/
- if (!sql_field)
+ if (!sql_field || (sql_field->invisible > INVISIBLE_USER &&
+ !column->generated))
{
my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
DBUG_RETURN(TRUE);
@@ -4742,7 +4742,8 @@ static bool append_system_key_parts(THD *thd, HA_CREATE_INFO *create_info,
break;
}
if (!key_part)
- key->columns.push_back(new Key_part_spec(&row_end_field, 0));
+ key->columns.push_back(new (thd->mem_root)
+ Key_part_spec(&row_end_field, 0, true));
}
key_it.rewind();
}
@@ -4772,8 +4773,10 @@ static bool append_system_key_parts(THD *thd, HA_CREATE_INFO *create_info,
return true;
}
}
- key->columns.push_back(new Key_part_spec(&period_end, 0));
- key->columns.push_back(new Key_part_spec(&period_start, 0));
+ key->columns.push_back(new (thd->mem_root)
+ Key_part_spec(&period_end, 0));
+ key->columns.push_back(new (thd->mem_root)
+ Key_part_spec(&period_start, 0));
}
}
@@ -8861,8 +8864,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
key_part_length= 0; // Use whole field
}
key_part_length /= kfield->charset()->mbmaxlen;
- key_parts.push_back(new (thd->mem_root) Key_part_spec(
- &cfield->field_name, key_part_length),
+ key_parts.push_back(new (thd->mem_root) Key_part_spec(&cfield->field_name,
+ key_part_length, true),
thd->mem_root);
}
if (table->s->tmp_table == NO_TMP_TABLE)
diff --git a/sql/sql_type.cc b/sql/sql_type.cc
index 22375d2962c..b7ad8c04af5 100644
--- a/sql/sql_type.cc
+++ b/sql/sql_type.cc
@@ -5703,10 +5703,12 @@ cmp_item *Type_handler_timestamp_common::make_cmp_item(THD *thd,
/***************************************************************************/
-static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y)
+static int srtcmp_in(const void *cs_, const void *x_, const void *y_)
{
- return cs->strnncollsp(x->ptr(), x->length(),
- y->ptr(), y->length());
+ const CHARSET_INFO *cs= static_cast<const CHARSET_INFO *>(cs_);
+ const String *x= static_cast<const String *>(x_);
+ const String *y= static_cast<const String *>(y_);
+ return cs->strnncollsp(x->ptr(), x->length(), y->ptr(), y->length());
}
in_vector *Type_handler_string_result::make_in_vector(THD *thd,
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index 5df9e7dd47d..07dd3b1f6ca 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -58,6 +58,8 @@ static udf_func *add_udf(LEX_CSTRING *name, Item_result ret,
const char *dl, Item_udftype typ);
static void del_udf(udf_func *udf);
static void *find_udf_dl(const char *dl);
+static bool find_udf_everywhere(THD* thd, const LEX_CSTRING &name,
+ TABLE *table);
static const char *init_syms(udf_func *tmp, char *nm)
{
@@ -430,6 +432,41 @@ static udf_func *add_udf(LEX_CSTRING *name, Item_result ret, const char *dl,
return tmp;
}
+/**
+ Find record with the udf in the udf func table
+
+ @param exact_name udf name
+ @param table table of mysql.func
+
+ @retval TRUE found
+ @retral FALSE not found
+*/
+
+static bool find_udf_in_table(const LEX_CSTRING &exact_name, TABLE *table)
+{
+ table->use_all_columns();
+ table->field[0]->store(exact_name.str, exact_name.length, &my_charset_bin);
+ return (!table->file->ha_index_read_idx_map(table->record[0], 0,
+ (uchar*) table->field[0]->ptr,
+ HA_WHOLE_KEY,
+ HA_READ_KEY_EXACT));
+}
+
+static bool remove_udf_in_table(const LEX_CSTRING &exact_name, TABLE *table)
+{
+ if (find_udf_in_table(exact_name, table))
+ {
+ int error;
+ if ((error= table->file->ha_delete_row(table->record[0])))
+ {
+ table->file->print_error(error, MYF(0));
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
/*
Drop user defined function.
@@ -446,8 +483,7 @@ static int mysql_drop_function_internal(THD *thd, udf_func *udf, TABLE *table)
{
DBUG_ENTER("mysql_drop_function_internal");
- const char *exact_name_str= udf->name.str;
- size_t exact_name_len= udf->name.length;
+ const LEX_CSTRING exact_name= udf->name;
del_udf(udf);
/*
@@ -460,18 +496,17 @@ static int mysql_drop_function_internal(THD *thd, udf_func *udf, TABLE *table)
if (!table)
DBUG_RETURN(1);
- table->use_all_columns();
- table->field[0]->store(exact_name_str, exact_name_len, &my_charset_bin);
- if (!table->file->ha_index_read_idx_map(table->record[0], 0,
- (uchar*) table->field[0]->ptr,
- HA_WHOLE_KEY,
- HA_READ_KEY_EXACT))
- {
- int error;
- if (unlikely((error= table->file->ha_delete_row(table->record[0]))))
- table->file->print_error(error, MYF(0));
- }
- DBUG_RETURN(0);
+ bool ret= remove_udf_in_table(exact_name, table);
+ DBUG_RETURN(ret);
+}
+
+
+static TABLE *open_udf_func_table(THD *thd)
+{
+ TABLE_LIST tables;
+ tables.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_FUNC_NAME,
+ &MYSQL_FUNC_NAME, TL_WRITE);
+ return open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT);
}
@@ -518,8 +553,7 @@ int mysql_create_function(THD *thd,udf_func *udf)
if (check_ident_length(&udf->name))
DBUG_RETURN(1);
- tables.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_FUNC_NAME, 0, TL_WRITE);
- table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT);
+ table= open_udf_func_table(thd);
mysql_rwlock_wrlock(&THR_LOCK_udf);
DEBUG_SYNC(current_thd, "mysql_create_function_after_lock");
@@ -620,42 +654,65 @@ err:
}
-int mysql_drop_function(THD *thd, const LEX_CSTRING *udf_name)
+enum drop_udf_result mysql_drop_function(THD *thd, const LEX_CSTRING *udf_name)
{
TABLE *table;
- TABLE_LIST tables;
udf_func *udf;
DBUG_ENTER("mysql_drop_function");
+ if (thd->locked_tables_mode)
+ {
+ my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
+ DBUG_RETURN(UDF_DEL_RESULT_ERROR);
+ }
+
+ if (!(table= open_udf_func_table(thd)))
+ DBUG_RETURN(UDF_DEL_RESULT_ERROR);
+
+ // Fast pre-check
+ if (!mysql_rwlock_tryrdlock(&THR_LOCK_udf))
+ {
+ bool found= find_udf_everywhere(thd, *udf_name, table);
+ mysql_rwlock_unlock(&THR_LOCK_udf);
+ if (!found)
+ {
+ close_mysql_tables(thd);
+ DBUG_RETURN(UDF_DEL_RESULT_ABSENT);
+ }
+ }
+
if (!initialized)
{
+ close_mysql_tables(thd);
if (opt_noacl)
- my_error(ER_FUNCTION_NOT_DEFINED, MYF(0), udf_name->str);
- else
- my_message(ER_OUT_OF_RESOURCES, ER_THD(thd, ER_OUT_OF_RESOURCES),
- MYF(0));
- DBUG_RETURN(1);
- }
+ DBUG_RETURN(UDF_DEL_RESULT_ABSENT); // SP should be checked
- tables.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_FUNC_NAME, 0, TL_WRITE);
- table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT);
+ my_message(ER_OUT_OF_RESOURCES, ER_THD(thd, ER_OUT_OF_RESOURCES), MYF(0));
+ DBUG_RETURN(UDF_DEL_RESULT_ERROR);
+ }
mysql_rwlock_wrlock(&THR_LOCK_udf);
+
+ // re-check under protection
+ if (!find_udf_everywhere(thd, *udf_name, table))
+ {
+ close_mysql_tables(thd);
+ mysql_rwlock_unlock(&THR_LOCK_udf);
+ DBUG_RETURN(UDF_DEL_RESULT_ABSENT);
+ }
+
+ if (check_access(thd, DELETE_ACL, "mysql", NULL, NULL, 1, 0))
+ goto err;
+
+
DEBUG_SYNC(current_thd, "mysql_drop_function_after_lock");
+
if (!(udf= (udf_func*) my_hash_search(&udf_hash, (uchar*) udf_name->str,
(uint) udf_name->length)) )
{
- if (thd->lex->check_exists)
- {
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
- ER_FUNCTION_NOT_DEFINED,
- ER_THD(thd, ER_FUNCTION_NOT_DEFINED),
- udf_name->str);
- goto done;
- }
-
- my_error(ER_FUNCTION_NOT_DEFINED, MYF(0), udf_name->str);
- goto err;
+ if (remove_udf_in_table(*udf_name, table))
+ goto err;
+ goto done;
}
if (mysql_drop_function_internal(thd, udf, table))
@@ -669,13 +726,24 @@ done:
while binlogging, to avoid binlog inconsistency.
*/
if (write_bin_log(thd, TRUE, thd->query(), thd->query_length()))
- DBUG_RETURN(1);
+ DBUG_RETURN(UDF_DEL_RESULT_ERROR);
- DBUG_RETURN(0);
+ close_mysql_tables(thd);
+ DBUG_RETURN(UDF_DEL_RESULT_DELETED);
err:
+ close_mysql_tables(thd);
mysql_rwlock_unlock(&THR_LOCK_udf);
- DBUG_RETURN(1);
+ DBUG_RETURN(UDF_DEL_RESULT_ERROR);
+}
+
+static bool find_udf_everywhere(THD* thd, const LEX_CSTRING &name,
+ TABLE *table)
+{
+ if (initialized && my_hash_search(&udf_hash, (uchar*) name.str, name.length))
+ return true;
+
+ return find_udf_in_table(name, table);
}
#endif /* HAVE_DLOPEN */
diff --git a/sql/sql_udf.h b/sql/sql_udf.h
index ac58a176fed..cb1954353fa 100644
--- a/sql/sql_udf.h
+++ b/sql/sql_udf.h
@@ -155,7 +155,13 @@ void udf_init(void),udf_free(void);
udf_func *find_udf(const char *name, size_t size, bool mark_used=0);
void free_udf(udf_func *udf);
int mysql_create_function(THD *thd,udf_func *udf);
-int mysql_drop_function(THD *thd, const LEX_CSTRING *name);
+enum drop_udf_result
+{
+ UDF_DEL_RESULT_ABSENT,
+ UDF_DEL_RESULT_DELETED,
+ UDF_DEL_RESULT_ERROR
+};
+enum drop_udf_result mysql_drop_function(THD *thd, const LEX_CSTRING *name);
#else
static inline void udf_init(void) { }
static inline void udf_free(void) { }
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index fccc2a426c4..2d360849928 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -542,6 +542,8 @@ int mysql_update(THD *thd,
query_plan.set_no_partitions();
if (thd->lex->describe || thd->lex->analyze_stmt)
goto produce_explain_and_leave;
+ if (thd->is_error())
+ DBUG_RETURN(1);
my_ok(thd); // No matching records
DBUG_RETURN(0);
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index e54b335e418..088e99f25c0 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2015, Oracle and/or its affiliates.
- Copyright (c) 2010, 2020, MariaDB Corporation.
+ Copyright (c) 2010, 2020, MariaDB
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
@@ -7757,6 +7757,8 @@ alter_list_item:
}
| ALTER opt_column opt_if_exists_table_element field_ident SET DEFAULT column_default_expr
{
+ if (check_expression($7, &$4, VCOL_DEFAULT))
+ MYSQL_YYABORT;
if (unlikely(Lex->add_alter_list($4, $7, $3)))
MYSQL_YYABORT;
}
@@ -14181,6 +14183,8 @@ backup_statements:
}
| LOCK_SYM
{
+ if (unlikely(Lex->sphead))
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "BACKUP LOCK"));
if (Lex->main_select_push())
MYSQL_YYABORT;
}
@@ -14194,6 +14198,8 @@ backup_statements:
}
| UNLOCK_SYM
{
+ if (unlikely(Lex->sphead))
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "BACKUP UNLOCK"));
/* Table list is empty for unlock */
Lex->sql_command= SQLCOM_BACKUP_LOCK;
}
diff --git a/sql/table.cc b/sql/table.cc
index 3d5e2343d2e..3cccc376bdf 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -8729,6 +8729,7 @@ int TABLE::period_make_insert(Item *src, Field *dst)
{
THD *thd= in_use;
+ file->store_auto_increment();
store_record(this, record[1]);
int res= src->save_in_field(dst, true);
@@ -8747,6 +8748,8 @@ int TABLE::period_make_insert(Item *src, Field *dst)
TRG_ACTION_AFTER, true);
restore_record(this, record[1]);
+ if (res)
+ file->restore_auto_increment();
return res;
}
diff --git a/sql/threadpool_common.cc b/sql/threadpool_common.cc
index 877428e67ac..e8eb0dcc29d 100644
--- a/sql/threadpool_common.cc
+++ b/sql/threadpool_common.cc
@@ -312,6 +312,16 @@ static void handle_wait_timeout(THD *thd)
thd->net.error= 2;
}
+/** Check if some client data is cached in thd->net or thd->net.vio */
+static bool has_unread_data(THD* thd)
+{
+ NET *net= &thd->net;
+ if (net->compress && net->remain_in_buf)
+ return true;
+ Vio *vio= net->vio;
+ return vio->has_data(vio);
+}
+
/**
Process a single client request or a single batch.
@@ -346,7 +356,6 @@ static int threadpool_process_request(THD *thd)
*/
for(;;)
{
- Vio *vio;
thd->net.reading_or_writing= 0;
if (mysql_audit_release_required(thd))
mysql_audit_release(thd);
@@ -362,8 +371,7 @@ static int threadpool_process_request(THD *thd)
set_thd_idle(thd);
- vio= thd->net.vio;
- if (!vio->has_data(vio))
+ if (!has_unread_data(thd))
{
/* More info on this debug sync is in sql_parse.cc*/
DEBUG_SYNC(thd, "before_do_command_net_read");
diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h
index 51c23085717..4461d73a928 100644
--- a/sql/wsrep_mysqld.h
+++ b/sql/wsrep_mysqld.h
@@ -158,7 +158,8 @@ extern const char* wsrep_provider_vendor;
extern char* wsrep_provider_capabilities;
extern char* wsrep_cluster_capabilities;
-int wsrep_show_status(THD *thd, SHOW_VAR *var, char *buff);
+int wsrep_show_status(THD *thd, SHOW_VAR *var, void *buff,
+ system_status_var *status_var, enum_var_type scope);
int wsrep_show_ready(THD *thd, SHOW_VAR *var, char *buff);
void wsrep_free_status(THD *thd);
void wsrep_update_cluster_state_uuid(const char* str);
diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc
index 40689b7cf88..d894fa6d555 100644
--- a/sql/wsrep_var.cc
+++ b/sql/wsrep_var.cc
@@ -938,7 +938,8 @@ static void export_wsrep_status_to_mysql(THD* thd)
mysql_status_vars[wsrep_status_len].type = SHOW_LONG;
}
-int wsrep_show_status (THD *thd, SHOW_VAR *var, char *buff)
+int wsrep_show_status (THD *thd, SHOW_VAR *var, void *,
+ system_status_var *, enum_var_type)
{
/* Note that we should allow show status like 'wsrep%' even
when WSREP(thd) is false. */