diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/backup.cc | 6 | ||||
-rw-r--r-- | sql/handler.cc | 23 | ||||
-rw-r--r-- | sql/log.cc | 9 | ||||
-rw-r--r-- | sql/log_event.cc | 2 | ||||
-rw-r--r-- | sql/mysqld.cc | 10 | ||||
-rw-r--r-- | sql/opt_range.cc | 20 | ||||
-rw-r--r-- | sql/share/errmsg-utf8.txt | 5 | ||||
-rw-r--r-- | sql/sql_class.cc | 2 | ||||
-rw-r--r-- | sql/sql_class.h | 18 | ||||
-rw-r--r-- | sql/sql_delete.cc | 3 | ||||
-rw-r--r-- | sql/sql_parse.cc | 54 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 4 | ||||
-rw-r--r-- | sql/sql_reload.cc | 10 | ||||
-rw-r--r-- | sql/sql_select.cc | 6 | ||||
-rw-r--r-- | sql/sql_show.cc | 5 | ||||
-rw-r--r-- | sql/sql_table.cc | 23 | ||||
-rw-r--r-- | sql/sql_type.cc | 8 | ||||
-rw-r--r-- | sql/sql_udf.cc | 148 | ||||
-rw-r--r-- | sql/sql_udf.h | 8 | ||||
-rw-r--r-- | sql/sql_update.cc | 2 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 8 | ||||
-rw-r--r-- | sql/table.cc | 3 | ||||
-rw-r--r-- | sql/threadpool_common.cc | 14 | ||||
-rw-r--r-- | sql/wsrep_mysqld.h | 3 | ||||
-rw-r--r-- | sql/wsrep_var.cc | 3 |
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. */ |