diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2020-12-01 19:51:14 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2020-12-01 19:51:14 +0200 |
commit | 589cf8dbf3accf57673d7e2f7a4435f7eaf33565 (patch) | |
tree | aa38a67d10f71fc781188341857e34d437fa9199 /sql | |
parent | a3531775b1efe06e2439a0c8ab668a2b69c859eb (diff) | |
parent | e30a05f4540b581df2e7d98bd7e812aeff603744 (diff) | |
download | mariadb-git-589cf8dbf3accf57673d7e2f7a4435f7eaf33565.tar.gz |
Merge 10.3 into 10.4
Diffstat (limited to 'sql')
43 files changed, 247 insertions, 223 deletions
diff --git a/sql/field.cc b/sql/field.cc index a7d5f6b3328..5a694b50fe0 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1887,13 +1887,8 @@ bool Field::compatible_field_size(uint field_metadata, int Field::store(const char *to, size_t length, CHARSET_INFO *cs, enum_check_fields check_level) { - int res; - THD *thd= get_thd(); - enum_check_fields old_check_level= thd->count_cuted_fields; - thd->count_cuted_fields= check_level; - res= store(to, length, cs); - thd->count_cuted_fields= old_check_level; - return res; + Check_level_instant_set check_level_save(get_thd(), check_level); + return store(to, length, cs); } diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 9f5f9766605..609e2135a99 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -4345,7 +4345,7 @@ int ha_partition::write_row(const uchar * buf) tmp_disable_binlog(thd); /* Do not replicate the low-level changes. */ error= m_file[part_id]->ha_write_row(buf); - if (have_auto_increment && !table->s->next_number_keypart) + if (!error && have_auto_increment && !table->s->next_number_keypart) set_auto_increment_if_higher(table->next_number_field); reenable_binlog(thd); diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 7d10dc19683..08b7d7cf8f2 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -92,7 +92,6 @@ public: bool auto_inc_initialized; mysql_mutex_t auto_inc_mutex; /**< protecting auto_inc val */ ulonglong next_auto_inc_val; /**< first non reserved value */ - ulonglong prev_auto_inc_val; /**< stored next_auto_inc_val */ /** Hash of partition names. Initialized in the first ha_partition::open() for the table_share. After that it is read-only, i.e. no locking required. @@ -104,7 +103,6 @@ public: Partition_share() : auto_inc_initialized(false), next_auto_inc_val(0), - prev_auto_inc_val(0), partition_name_hash_initialized(false), partition_names(NULL) { @@ -430,24 +428,6 @@ private: MY_BITMAP m_locked_partitions; /** Stores shared auto_increment etc. */ Partition_share *part_share; - /** Fix spurious -Werror=overloaded-virtual in GCC 9 */ - virtual void restore_auto_increment(ulonglong prev_insert_id) override - { - handler::restore_auto_increment(prev_insert_id); - } - /** Store and restore next_auto_inc_val over duplicate key errors. */ - void store_auto_increment() override - { - DBUG_ASSERT(part_share); - part_share->prev_auto_inc_val= part_share->next_auto_inc_val; - handler::store_auto_increment(); - } - void restore_auto_increment() override - { - DBUG_ASSERT(part_share); - part_share->next_auto_inc_val= part_share->prev_auto_inc_val; - handler::restore_auto_increment(); - } void sum_copy_info(handler *file); void sum_copy_infos(); void reset_copy_info() override; diff --git a/sql/handler.cc b/sql/handler.cc index 2553cd22a59..ed12830ce20 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -3310,7 +3310,6 @@ int handler::update_auto_increment() THD *thd= table->in_use; struct system_variables *variables= &thd->variables; int result=0, tmp; - enum enum_check_fields save_count_cuted_fields; DBUG_ENTER("handler::update_auto_increment"); /* @@ -3452,10 +3451,10 @@ int handler::update_auto_increment() nr, append ? nb_reserved_values : 0)); /* Store field without warning (Warning will be printed by insert) */ - save_count_cuted_fields= thd->count_cuted_fields; - thd->count_cuted_fields= CHECK_FIELD_IGNORE; - tmp= table->next_number_field->store((longlong)nr, TRUE); - thd->count_cuted_fields= save_count_cuted_fields; + { + Check_level_instant_set check_level_save(thd, CHECK_FIELD_IGNORE); + tmp= table->next_number_field->store((longlong)nr, TRUE); + } if (unlikely(tmp)) // Out of range value in store { diff --git a/sql/handler.h b/sql/handler.h index c516ea4bfc4..0c8be2154a9 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -3149,10 +3149,6 @@ private: */ Handler_share **ha_share; - /** Stores next_insert_id for handling duplicate key errors. */ - ulonglong m_prev_insert_id; - - public: handler(handlerton *ht_arg, TABLE_SHARE *share_arg) :table_share(share_arg), table(0), @@ -3177,7 +3173,7 @@ public: auto_inc_intervals_count(0), m_psi(NULL), set_top_table_fields(FALSE), top_table(0), top_table_field(0), top_table_fields(0), - m_lock_type(F_UNLCK), ha_share(NULL), m_prev_insert_id(0) + m_lock_type(F_UNLCK), ha_share(NULL) { DBUG_PRINT("info", ("handler created F_UNLCK %d F_RDLCK %d F_WRLCK %d", @@ -3858,16 +3854,6 @@ public: insert_id_for_cur_row; } - /** Store and restore next_insert_id over duplicate key errors. */ - virtual void store_auto_increment() - { - m_prev_insert_id= next_insert_id; - } - virtual void restore_auto_increment() - { - restore_auto_increment(m_prev_insert_id); - } - virtual void update_create_info(HA_CREATE_INFO *create_info) {} int check_old_types(); virtual int assign_to_keycache(THD* thd, HA_CHECK_OPT* check_opt) diff --git a/sql/item.cc b/sql/item.cc index 26e99fe752e..f700bcfe680 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1419,18 +1419,13 @@ int Item::save_in_field_no_warnings(Field *field, bool no_conversions) int res; TABLE *table= field->table; THD *thd= table->in_use; - enum_check_fields tmp= thd->count_cuted_fields; - my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set); - sql_mode_t sql_mode= thd->variables.sql_mode; + Check_level_instant_set check_level_save(thd, CHECK_FIELD_IGNORE); + Sql_mode_save sql_mode(thd); thd->variables.sql_mode&= ~(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE); thd->variables.sql_mode|= MODE_INVALID_DATES; - thd->count_cuted_fields= CHECK_FIELD_IGNORE; - + my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set); res= save_in_field(field, no_conversions); - - thd->count_cuted_fields= tmp; dbug_tmp_restore_column_map(table->write_set, old_map); - thd->variables.sql_mode= sql_mode; return res; } diff --git a/sql/item.h b/sql/item.h index 2b49487d677..e2e18ce9b86 100644 --- a/sql/item.h +++ b/sql/item.h @@ -951,6 +951,11 @@ public: void set_name_no_truncate(THD *thd, const char *str, uint length, CHARSET_INFO *cs); void init_make_send_field(Send_field *tmp_field, const Type_handler *h); + void share_name_with(const Item *item) + { + name= item->name; + is_autogenerated_name= item->is_autogenerated_name; + } virtual void cleanup(); virtual void make_send_field(THD *thd, Send_field *field); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index bf992886eda..c43dbcaab78 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -319,19 +319,18 @@ static bool convert_const_to_int(THD *thd, Item_field *field_item, if ((*item)->const_item() && !(*item)->is_expensive()) { TABLE *table= field->table; - sql_mode_t orig_sql_mode= thd->variables.sql_mode; - enum_check_fields orig_count_cuted_fields= thd->count_cuted_fields; + Sql_mode_save sql_mode(thd); + Check_level_instant_set check_level_save(thd, CHECK_FIELD_IGNORE); my_bitmap_map *old_maps[2] = { NULL, NULL }; ulonglong UNINIT_VAR(orig_field_val); /* original field value if valid */ /* table->read_set may not be set if we come here from a CREATE TABLE */ if (table && table->read_set) - dbug_tmp_use_all_columns(table, old_maps, + dbug_tmp_use_all_columns(table, old_maps, table->read_set, table->write_set); /* For comparison purposes allow invalid dates like 2000-01-32 */ - thd->variables.sql_mode= (orig_sql_mode & ~MODE_NO_ZERO_DATE) | + thd->variables.sql_mode= (thd->variables.sql_mode & ~MODE_NO_ZERO_DATE) | MODE_INVALID_DATES; - thd->count_cuted_fields= CHECK_FIELD_IGNORE; /* Store the value of the field/constant because the call to save_in_field @@ -368,8 +367,6 @@ static bool convert_const_to_int(THD *thd, Item_field *field_item, /* orig_field_val must be a valid value that can be restored back. */ DBUG_ASSERT(!result); } - thd->variables.sql_mode= orig_sql_mode; - thd->count_cuted_fields= orig_count_cuted_fields; if (table && table->read_set) dbug_tmp_restore_column_maps(table->read_set, table->write_set, old_maps); } diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 7887724358d..e2058475d0e 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1484,7 +1484,8 @@ Item_in_subselect::Item_in_subselect(THD *thd, Item * left_exp, pushed_cond_guards(NULL), do_not_convert_to_sj(FALSE), is_jtbm_merged(FALSE), is_jtbm_const_tab(FALSE), is_flattenable_semijoin(FALSE), is_registered_semijoin(FALSE), - upper_item(0) + upper_item(0), + converted_from_in_predicate(FALSE) { DBUG_ENTER("Item_in_subselect::Item_in_subselect"); DBUG_PRINT("info", ("in_strategy: %u", (uint)in_strategy)); diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 99bb5b190c2..16a4735359b 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -610,12 +610,18 @@ public: Item_func_not_all *upper_item; // point on NOT/NOP before ALL/SOME subquery + /* + SET to TRUE if IN subquery is converted from an IN predicate + */ + bool converted_from_in_predicate; + Item_in_subselect(THD *thd_arg, Item * left_expr, st_select_lex *select_lex); Item_in_subselect(THD *thd_arg): Item_exists_subselect(thd_arg), left_expr_cache(0), first_execution(TRUE), in_strategy(SUBS_NOT_TRANSFORMED), pushed_cond_guards(NULL), func(NULL), do_not_convert_to_sj(FALSE), - is_jtbm_merged(FALSE), is_jtbm_const_tab(FALSE), upper_item(0) {} + is_jtbm_merged(FALSE), is_jtbm_const_tab(FALSE), upper_item(0), + converted_from_in_predicate(FALSE) {} void cleanup(); subs_type substype() { return IN_SUBS; } void reset() diff --git a/sql/log_event.cc b/sql/log_event.cc index b06336669f3..6871eeda79e 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -7570,10 +7570,10 @@ error: if (thd->transaction_rollback_request) { trans_rollback_implicit(thd); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); } else if (! thd->in_multi_stmt_transaction_mode()) - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); else thd->mdl_context.release_statement_locks(); @@ -9047,7 +9047,8 @@ int Xid_log_event::do_apply_event(rpl_group_info *rgi) "COMMIT /* implicit, from Xid_log_event */"); thd->variables.option_bits&= ~OPTION_GTID_BEGIN; res= trans_commit(thd); /* Automatically rolls back on error. */ - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); + #ifdef WITH_WSREP if (WSREP(thd)) mysql_mutex_lock(&thd->LOCK_thd_data); if ((!res || (WSREP(thd) && thd->wsrep_trx().state() == wsrep::transaction::s_must_replay )) && sub_id) diff --git a/sql/mdl.cc b/sql/mdl.cc index 54128c2ee97..ebe1bb75927 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -3036,6 +3036,9 @@ void MDL_context::rollback_to_savepoint(const MDL_savepoint &mdl_savepoint) void MDL_context::release_transactional_locks() { DBUG_ENTER("MDL_context::release_transactional_locks"); + /* Fail if there are active transactions */ + DBUG_ASSERT(!(current_thd->server_status & + (SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY))); release_locks_stored_before(MDL_STATEMENT, NULL); release_locks_stored_before(MDL_TRANSACTION, NULL); DBUG_VOID_RETURN; diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 62af68262ba..f7349e7a1bf 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -868,6 +868,7 @@ bool subquery_types_allow_materialization(THD* thd, Item_in_subselect *in_subs) bool all_are_fields= TRUE; uint32 total_key_length = 0; + bool converted_from_in_predicate= in_subs->converted_from_in_predicate; for (uint i= 0; i < elements; i++) { Item *outer= in_subs->left_expr->element_index(i); @@ -875,8 +876,11 @@ bool subquery_types_allow_materialization(THD* thd, Item_in_subselect *in_subs) all_are_fields &= (outer->real_item()->type() == Item::FIELD_ITEM && inner->real_item()->type() == Item::FIELD_ITEM); total_key_length += inner->max_length; - if (!inner->type_handler()->subquery_type_allows_materialization(inner, - outer)) + if (!inner-> + type_handler()-> + subquery_type_allows_materialization(inner, + outer, + converted_from_in_predicate)) { trace_transform.add("possible", false); trace_transform.add("cause", "types mismatch"); diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc index f58df09623c..88e6447ddcc 100644 --- a/sql/rpl_gtid.cc +++ b/sql/rpl_gtid.cc @@ -441,7 +441,7 @@ rpl_slave_state::truncate_state_table(THD *thd) close_thread_tables(thd); ha_commit_trans(thd, TRUE); } - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); } reenable_binlog(thd); @@ -988,7 +988,7 @@ end: ha_rollback_trans(thd, FALSE); } close_thread_tables(thd); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); thd->lex->restore_backup_query_tables_list(&lex_backup); if (err) diff --git a/sql/rpl_injector.cc b/sql/rpl_injector.cc index 597a357e4e2..442d28fceb3 100644 --- a/sql/rpl_injector.cc +++ b/sql/rpl_injector.cc @@ -68,34 +68,34 @@ injector::transaction::~transaction() */ int injector::transaction::commit() { - DBUG_ENTER("injector::transaction::commit()"); - int error= m_thd->binlog_flush_pending_rows_event(true); - /* - Cluster replication does not preserve statement or - transaction boundaries of the master. Instead, a new - transaction on replication slave is started when a new GCI - (global checkpoint identifier) is issued, and is committed - when the last event of the check point has been received and - processed. This ensures consistency of each cluster in - cluster replication, and there is no requirement for stronger - consistency: MySQL replication is asynchronous with other - engines as well. - - A practical consequence of that is that row level replication - stream passed through the injector thread never contains - COMMIT events. - Here we should preserve the server invariant that there is no - outstanding statement transaction when the normal transaction - is committed by committing the statement transaction - explicitly. - */ - trans_commit_stmt(m_thd); - if (!trans_commit(m_thd)) - { - close_thread_tables(m_thd); - m_thd->mdl_context.release_transactional_locks(); - } - DBUG_RETURN(error); + DBUG_ENTER("injector::transaction::commit()"); + int error= m_thd->binlog_flush_pending_rows_event(true); + /* + Cluster replication does not preserve statement or + transaction boundaries of the master. Instead, a new + transaction on replication slave is started when a new GCI + (global checkpoint identifier) is issued, and is committed + when the last event of the check point has been received and + processed. This ensures consistency of each cluster in + cluster replication, and there is no requirement for stronger + consistency: MySQL replication is asynchronous with other + engines as well. + + A practical consequence of that is that row level replication + stream passed through the injector thread never contains + COMMIT events. + Here we should preserve the server invariant that there is no + outstanding statement transaction when the normal transaction + is committed by committing the statement transaction + explicitly. + */ + trans_commit_stmt(m_thd); + if (!trans_commit(m_thd)) + { + close_thread_tables(m_thd); + m_thd->release_transactional_locks(); + } + DBUG_RETURN(error); } diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 241d8321749..39b2fa38515 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -1702,7 +1702,7 @@ scan_all_gtid_slave_pos_table(THD *thd, int (*cb)(THD *, LEX_CSTRING *, void *), { my_error(ER_FILE_NOT_FOUND, MYF(0), path, my_errno); close_thread_tables(thd); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); return 1; } else @@ -1715,7 +1715,7 @@ scan_all_gtid_slave_pos_table(THD *thd, int (*cb)(THD *, LEX_CSTRING *, void *), err= ha_discover_table_names(thd, &MYSQL_SCHEMA_NAME, dirp, &tl, false); my_dirend(dirp); close_thread_tables(thd); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); if (err) return err; @@ -2000,7 +2000,7 @@ end: ha_commit_trans(thd, FALSE); ha_commit_trans(thd, TRUE); close_thread_tables(thd); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); } return err; @@ -2282,7 +2282,7 @@ void rpl_group_info::cleanup_context(THD *thd, bool error) if (unlikely(error)) { - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); if (thd == rli->sql_driver_thd) { @@ -2396,10 +2396,10 @@ void rpl_group_info::slave_close_thread_tables(THD *thd) if (thd->transaction_rollback_request) { trans_rollback_implicit(thd); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); } else if (! thd->in_multi_stmt_transaction_mode()) - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); else thd->mdl_context.release_statement_locks(); diff --git a/sql/sp.cc b/sql/sp.cc index 081edcd725e..0b553ebf7a1 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1181,8 +1181,6 @@ Sp_handler::sp_create_routine(THD *thd, const sp_head *sp) const CHARSET_INFO *db_cs= get_default_db_collation(thd, sp->m_db.str); - enum_check_fields saved_count_cuted_fields; - bool store_failed= FALSE; DBUG_ENTER("sp_create_routine"); DBUG_PRINT("enter", ("type: %s name: %.*s", @@ -1216,8 +1214,7 @@ Sp_handler::sp_create_routine(THD *thd, const sp_head *sp) const /* Reset sql_mode during data dictionary operations. */ thd->variables.sql_mode= 0; - saved_count_cuted_fields= thd->count_cuted_fields; - thd->count_cuted_fields= CHECK_FIELD_WARN; + Check_level_instant_set check_level_save(thd, CHECK_FIELD_WARN); if (!(table= open_proc_table_for_update(thd))) { @@ -1477,7 +1474,6 @@ log: ret= FALSE; done: - thd->count_cuted_fields= saved_count_cuted_fields; thd->variables.sql_mode= saved_mode; DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); DBUG_RETURN(ret); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index e91364b0c0a..aa4f80907f5 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -2311,10 +2311,10 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) if (thd->transaction_rollback_request) { trans_rollback_implicit(thd); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); } else if (! thd->in_multi_stmt_transaction_mode()) - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); else thd->mdl_context.release_statement_locks(); } @@ -3442,10 +3442,10 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, if (thd->transaction_rollback_request) { trans_rollback_implicit(thd); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); } else if (! thd->in_multi_stmt_transaction_mode()) - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); else thd->mdl_context.release_statement_locks(); } diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 57e8411b084..0769e1eb395 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -9312,6 +9312,8 @@ static bool show_global_privileges(THD *thd, ACL_USER_BASE *acl_entry, add_user_parameters(thd, &global, (ACL_USER *)acl_entry, (want_access & GRANT_ACL)); + else if (want_access & GRANT_ACL) + global.append(STRING_WITH_LEN(" WITH GRANT OPTION")); protocol->prepare_for_resend(); protocol->store(global.ptr(),global.length(),global.charset()); if (protocol->write()) diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index 37aab267511..0a6e76d117f 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2010, 2015, Oracle and/or its affiliates. - Copyright (c) 2011, 2019, MariaDB + Copyright (c) 2011, 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 @@ -43,7 +43,7 @@ static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list) trans_rollback_stmt(thd); trans_rollback(thd); close_thread_tables(thd); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); /* table_list->table has been closed and freed. Do not reference @@ -116,7 +116,7 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, acquire the exclusive lock to satisfy MDL asserts and avoid deadlocks. */ - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); /* Attempt to do full-blown table open in mysql_admin_table() has failed. Let us try to open at least a .FRM for this table. @@ -285,7 +285,7 @@ end: } /* In case of a temporary table there will be no metadata lock. */ if (unlikely(error) && has_mdl_lock) - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); DBUG_RETURN(error); } @@ -614,7 +614,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, trans_rollback(thd); close_thread_tables(thd); table->table= NULL; - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); table->mdl_request.init(MDL_key::TABLE, table->db.str, table->table_name.str, MDL_SHARED_NO_READ_WRITE, MDL_TRANSACTION); } @@ -674,7 +674,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, trans_rollback_stmt(thd); trans_rollback(thd); close_thread_tables(thd); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); DBUG_PRINT("admin", ("simple error, admin next table")); continue; case -1: // error, message could be written to net @@ -741,7 +741,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, trans_commit_stmt(thd); trans_commit(thd); close_thread_tables(thd); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); lex->reset_query_tables_list(FALSE); /* Restore Query_tables_list::sql_command value to make statement @@ -874,7 +874,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, thd->open_options|= extra_open_options; close_thread_tables(thd); table->table= NULL; - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); table->mdl_request.init(MDL_key::TABLE, table->db.str, table->table_name.str, MDL_SHARED_NO_READ_WRITE, MDL_TRANSACTION); table->mdl_request.set_type(MDL_SHARED_READ); @@ -1106,7 +1106,7 @@ send_result_message: trans_commit_stmt(thd); trans_commit(thd); close_thread_tables(thd); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); /* Clear references to TABLE and MDL_ticket after releasing them. */ table->mdl_request.ticket= NULL; @@ -1259,7 +1259,7 @@ send_result_message: goto err; } close_thread_tables(thd); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); /* If it is CHECK TABLE v1, v2, v3, and v1, v2, v3 are views, we will run @@ -1297,7 +1297,7 @@ err: table->table= 0; } close_thread_tables(thd); // Shouldn't be needed - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); thd->resume_subsequent_commits(suspended_wfc); DBUG_RETURN(TRUE); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 4be70abb7db..868d76572e3 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -9149,7 +9149,7 @@ close_mysql_tables(THD *thd) if (! thd->in_sub_stmt) trans_commit_stmt(thd); close_thread_tables(thd); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); } /* diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 041574485fe..573e4318682 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -4824,7 +4824,7 @@ void destroy_thd(MYSQL_THD thd) void reset_thd(MYSQL_THD thd) { close_thread_tables(thd); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); thd->free_items(); free_root(thd->mem_root, MYF(MY_KEEP_PREALLOC)); } diff --git a/sql/sql_class.h b/sql/sql_class.h index 41b69742834..845e392eff7 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -4574,6 +4574,13 @@ public: locked_tables_mode= mode_arg; } void leave_locked_tables_mode(); + /* Relesae transactional locks if there are no active transactions */ + void release_transactional_locks() + { + if (!(server_status & + (SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY))) + mdl_context.release_transactional_locks(); + } int decide_logging_format(TABLE_LIST *tables); /* In Some cases when decide_logging_format is called it does not have all @@ -6745,6 +6752,23 @@ class Switch_to_definer_security_ctx }; +class Check_level_instant_set +{ + THD *m_thd; + enum_check_fields m_check_level; +public: + Check_level_instant_set(THD *thd, enum_check_fields temporary_value) + :m_thd(thd), m_check_level(thd->count_cuted_fields) + { + thd->count_cuted_fields= temporary_value; + } + ~Check_level_instant_set() + { + m_thd->count_cuted_fields= m_check_level; + } +}; + + /** This class resembles the SQL Standard schema qualified object name: <schema qualified name> ::= [ <schema name> <period> ] <qualified identifier> diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index a4ef698590c..5d006a7518c 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -260,7 +260,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(); + ulonglong prev_insert_id= table->file->next_insert_id; store_record(table, record[1]); if (likely(!res)) res= src->save_in_field(table->field[dst_fieldno], true); @@ -276,7 +276,7 @@ int update_portion_of_time(THD *thd, TABLE *table, TRG_ACTION_AFTER, true); restore_record(table, record[1]); if (res) - table->file->restore_auto_increment(); + table->file->restore_auto_increment(prev_insert_id); if (likely(!res) && lcond && rcond) res= table->period_make_insert(period_conds.end.item, diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 3b312225937..1e416c307cf 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -1402,7 +1402,8 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived) DBUG_RETURN(false); st_select_lex_unit *unit= derived->get_unit(); - st_select_lex *sl= unit->first_select(); + st_select_lex *first_sl= unit->first_select(); + st_select_lex *sl= first_sl; if (derived->prohibit_cond_pushdown) DBUG_RETURN(false); @@ -1461,6 +1462,20 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived) if (!extracted_cond_copy) continue; + /* + Rename the columns of all non-first selects of a union to be compatible + by names with the columns of the first select. It will allow to use copies + of the same expression pushed into having clauses of different selects. + */ + if (sl != first_sl) + { + DBUG_ASSERT(sl->item_list.elements == first_sl->item_list.elements); + List_iterator_fast<Item> it(sl->item_list); + List_iterator_fast<Item> nm_it(unit->types); + while (Item *item= it++) + item->share_name_with(nm_it++); + } + /* Collect fields that are used in the GROUP BY of sl */ if (sl->have_window_funcs()) { @@ -1481,7 +1496,7 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived) &remaining_cond, &Item::derived_field_transformer_for_where, (uchar *) sl); - + if (!remaining_cond) continue; /* diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 7dd83d625e8..b8d11cd778f 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1721,7 +1721,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) int error, trg_error= 0; char *key=0; MY_BITMAP *save_read_set, *save_write_set; - table->file->store_auto_increment(); + ulonglong prev_insert_id= table->file->next_insert_id; ulonglong insert_id_for_cur_row= 0; ulonglong prev_insert_id_for_cur_row= 0; DBUG_ENTER("write_record"); @@ -1870,7 +1870,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) if (res == VIEW_CHECK_ERROR) goto before_trg_err; - table->file->restore_auto_increment(); + table->file->restore_auto_increment(prev_insert_id); info->touched++; if (different_records) { @@ -2064,7 +2064,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) if (!(thd->variables.old_behavior & OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE)) table->file->print_error(error, MYF(ME_WARNING)); - table->file->restore_auto_increment(); + table->file->restore_auto_increment(prev_insert_id); goto ok_or_after_trg_err; } @@ -2087,7 +2087,7 @@ err: table->file->print_error(error,MYF(0)); before_trg_err: - table->file->restore_auto_increment(); + table->file->restore_auto_increment(prev_insert_id); if (key) my_safe_afree(key, table->s->max_unique_length); table->column_bitmaps_set(save_read_set, save_write_set); @@ -3061,7 +3061,7 @@ pthread_handler_t handle_delayed_insert(void *arg) if (thd->mdl_context.clone_ticket(&di->grl_protection) || thd->mdl_context.clone_ticket(&di->table_list.mdl_request)) { - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); di->handler_thread_initialized= TRUE; goto err; } @@ -3276,7 +3276,7 @@ pthread_handler_t handle_delayed_insert(void *arg) thd->set_killed(KILL_CONNECTION_HARD); // If error close_thread_tables(thd); // Free the table - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); mysql_cond_broadcast(&di->cond_client); // Safety mysql_mutex_lock(&LOCK_delayed_create); // Because of delayed_get_table @@ -4766,6 +4766,7 @@ bool select_create::send_eof() WSREP_ERROR("Appending table key for CTAS failed: %s, %d", (wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void", rcode); + abort_result_set(); DBUG_RETURN(true); } /* If commit fails, we should be able to reset the OK status. */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 8cb25197ea2..036c1215ea6 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2057,7 +2057,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, locks. */ trans_rollback_implicit(thd); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); } thd->cleanup_after_query(); @@ -2122,7 +2122,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ulonglong options= (ulonglong) (uchar) packet[0]; if (trans_commit_implicit(thd)) break; - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); if (check_global_access(thd,RELOAD_ACL)) break; general_log_print(thd, command, NullS); @@ -2157,7 +2157,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if (trans_commit_implicit(thd)) break; close_thread_tables(thd); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); my_ok(thd); break; } @@ -2993,7 +2993,7 @@ err: /* Close tables and release metadata locks. */ close_thread_tables(thd); DBUG_ASSERT(!thd->locked_tables_mode); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); return TRUE; } @@ -3733,7 +3733,7 @@ mysql_execute_command(THD *thd) /* Commit the normal transaction if one is active. */ bool commit_failed= trans_commit_implicit(thd); /* Release metadata locks acquired in this transaction. */ - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); if (commit_failed) { WSREP_DEBUG("implicit commit failed, MDL released: %lld", @@ -5011,7 +5011,7 @@ mysql_execute_command(THD *thd) { res= trans_commit_implicit(thd); thd->locked_tables_list.unlock_locked_tables(thd); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); thd->variables.option_bits&= ~(OPTION_TABLE_LOCK); } if (thd->global_read_lock.is_acquired() && @@ -5026,7 +5026,7 @@ mysql_execute_command(THD *thd) res= trans_commit_implicit(thd); thd->locked_tables_list.unlock_locked_tables(thd); /* Release transactional metadata locks. */ - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); if (res) goto error; @@ -5644,7 +5644,7 @@ mysql_execute_command(THD *thd) DBUG_PRINT("info", ("Executing SQLCOM_BEGIN thd: %p", thd)); if (trans_begin(thd, lex->start_transaction_opt)) { - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); WSREP_DEBUG("BEGIN failed, MDL released: %lld", (longlong) thd->thread_id); WSREP_DEBUG("stmt_da, sql_errno: %d", (thd->get_stmt_da()->is_error()) ? thd->get_stmt_da()->sql_errno() : 0); @@ -5663,7 +5663,7 @@ mysql_execute_command(THD *thd) (thd->variables.completion_type == 2 && lex->tx_release != TVL_NO)); bool commit_failed= trans_commit(thd); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); if (commit_failed) { WSREP_DEBUG("COMMIT failed, MDL released: %lld", @@ -5701,7 +5701,7 @@ mysql_execute_command(THD *thd) (thd->variables.completion_type == 2 && lex->tx_release != TVL_NO)); bool rollback_failed= trans_rollback(thd); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); if (rollback_failed) { @@ -6004,7 +6004,6 @@ mysql_execute_command(THD *thd) case SQLCOM_XA_COMMIT: { bool commit_failed= trans_xa_commit(thd); - thd->mdl_context.release_transactional_locks(); if (commit_failed) { WSREP_DEBUG("XA commit failed, MDL released: %lld", @@ -6022,7 +6021,6 @@ mysql_execute_command(THD *thd) case SQLCOM_XA_ROLLBACK: { bool rollback_failed= trans_xa_rollback(thd); - thd->mdl_context.release_transactional_locks(); if (rollback_failed) { WSREP_DEBUG("XA rollback failed, MDL released: %lld", @@ -6227,7 +6225,7 @@ finish: */ THD_STAGE_INFO(thd, stage_rollback_implicit); trans_rollback_implicit(thd); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); } else if (stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_END)) { @@ -6241,7 +6239,7 @@ finish: /* Commit the normal transaction if one is active. */ trans_commit_implicit(thd); thd->get_stmt_da()->set_overwrite_status(false); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); } } else if (! thd->in_sub_stmt && ! thd->in_multi_stmt_transaction_mode()) @@ -6256,7 +6254,7 @@ finish: - If in autocommit mode, or outside a transactional context, automatically release metadata locks of the current statement. */ - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); } else if (! thd->in_sub_stmt) { @@ -6281,7 +6279,7 @@ finish: { WSREP_DEBUG("Forcing release of transactional locks for thd: %lld", (longlong) thd->thread_id); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); } /* diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 849d1895fa1..ee504028074 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -4270,7 +4270,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) if (thd->transaction_rollback_request) { trans_rollback_implicit(thd); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); } /* Preserve CHANGE MASTER attributes */ diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 123d20698be..9671880f1e0 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -24035,8 +24035,7 @@ cmp_buffer_with_ref(THD *thd, TABLE *table, TABLE_REF *tab_ref) bool cp_buffer_from_ref(THD *thd, TABLE *table, TABLE_REF *ref) { - enum enum_check_fields save_count_cuted_fields= thd->count_cuted_fields; - thd->count_cuted_fields= CHECK_FIELD_IGNORE; + Check_level_instant_set check_level_save(thd, CHECK_FIELD_IGNORE); my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set); bool result= 0; @@ -24048,7 +24047,6 @@ cp_buffer_from_ref(THD *thd, TABLE *table, TABLE_REF *ref) break; } } - thd->count_cuted_fields= save_count_cuted_fields; dbug_tmp_restore_column_map(table->write_set, old_map); return result; } diff --git a/sql/sql_select.h b/sql/sql_select.h index 3ac8c152ffc..e14907d73bc 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1900,18 +1900,11 @@ public: { enum store_key_result result; THD *thd= to_field->table->in_use; - enum_check_fields saved_count_cuted_fields= thd->count_cuted_fields; - sql_mode_t orig_sql_mode= thd->variables.sql_mode; + Check_level_instant_set check_level_save(thd, CHECK_FIELD_IGNORE); + Sql_mode_save sql_mode(thd); thd->variables.sql_mode&= ~(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE); thd->variables.sql_mode|= MODE_INVALID_DATES; - - thd->count_cuted_fields= CHECK_FIELD_IGNORE; - result= copy_inner(); - - thd->count_cuted_fields= saved_count_cuted_fields; - thd->variables.sql_mode= orig_sql_mode; - return result; } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 29ee8ef2fb1..1fdd2d7c8d0 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -3732,7 +3732,6 @@ static bool show_status_array(THD *thd, const char *wild, char name_buffer[NAME_CHAR_LEN]; int len; SHOW_VAR tmp, *var; - enum_check_fields save_count_cuted_fields= thd->count_cuted_fields; bool res= FALSE; CHARSET_INFO *charset= system_charset_info; DBUG_ENTER("show_status_array"); @@ -3855,7 +3854,6 @@ static bool show_status_array(THD *thd, const char *wild, } } end: - thd->count_cuted_fields= save_count_cuted_fields; DBUG_RETURN(res); } @@ -4583,8 +4581,7 @@ fill_schema_table_by_open(THD *thd, MEM_ROOT *mem_root, Open_tables_backup *open_tables_state_backup, bool can_deadlock) { - Query_arena i_s_arena(mem_root, - Query_arena::STMT_CONVENTIONAL_EXECUTION), + Query_arena i_s_arena(mem_root, Query_arena::STMT_CONVENTIONAL_EXECUTION), backup_arena, *old_arena; LEX *old_lex= thd->lex, temp_lex, *lex; LEX_CSTRING db_name, table_name; @@ -5098,12 +5095,9 @@ end: class Warnings_only_error_handler : public Internal_error_handler { public: - bool handle_condition(THD *thd, - uint sql_errno, - const char* sqlstate, + bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, Sql_condition::enum_warning_level *level, - const char* msg, - Sql_condition ** cond_hdl) + const char* msg, Sql_condition ** cond_hdl) { if (sql_errno == ER_TRG_NO_DEFINER || sql_errno == ER_TRG_NO_CREATION_CTX) return true; @@ -8721,13 +8715,6 @@ static int optimize_schema_tables_memory_usage(TABLE_LIST *table_list) DBUG_ASSERT(table->s->keys == 0); DBUG_ASSERT(table->s->uniques == 0); - // XXX HACK HACK HACK: in a stored function, RETURN (SELECT ...) - // enables warnings (in THD::sp_eval_expr) for the whole val_xxx/store pair, - // while the intention is to warn only for store(). Until this is - // fixed let's avoid data truncation warnings in I_S->fill_table() - if (thd->count_cuted_fields == CHECK_FIELD_IGNORE) - { - uchar *cur= table->field[0]->ptr; /* first recinfo could be a NULL bitmap, not an actual Field */ from_recinfo= to_recinfo= p->start_recinfo + (cur != table->record[0]); @@ -8761,7 +8748,6 @@ static int optimize_schema_tables_memory_usage(TABLE_LIST *table_list) to_recinfo++; } p->recinfo= to_recinfo; - } // XXX end of HACK HACK HACK // TODO switch from Aria to Memory if all blobs were optimized away? if (instantiate_tmp_table(table, p->keyinfo, p->start_recinfo, &p->recinfo, @@ -8924,6 +8910,7 @@ bool get_schema_tables_result(JOIN *join, } Switch_to_definer_security_ctx backup_ctx(thd, table_list); + Check_level_instant_set check_level_save(thd, CHECK_FIELD_IGNORE); if (table_list->schema_table->fill_table(thd, table_list, cond)) { result= 1; diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index ed569d6eab8..717deeabe18 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -2893,7 +2893,6 @@ int read_statistics_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables) Field **field_ptr; KEY *key_info, *key_info_end; TABLE_SHARE *table_share= table->s; - enum_check_fields old_check_level= thd->count_cuted_fields; DBUG_ENTER("read_statistics_for_table"); DEBUG_SYNC(thd, "statistics_mem_alloc_start1"); @@ -2909,7 +2908,7 @@ int read_statistics_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables) } /* Don't write warnings for internal field conversions */ - thd->count_cuted_fields= CHECK_FIELD_IGNORE; + Check_level_instant_set check_level_save(thd, CHECK_FIELD_IGNORE); /* Read statistics from the statistical table table_stats */ Table_statistics *read_stats= table_share->stats_cb.table_stats; @@ -2991,7 +2990,6 @@ int read_statistics_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables) } } - thd->count_cuted_fields= old_check_level; table_share->stats_cb.end_stats_load(); DBUG_RETURN(0); } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 942b838c692..6a52b7d418e 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -10149,16 +10149,14 @@ do_continue:; if (use_inplace) { table->s->frm_image= &frm; - enum_check_fields save_count_cuted_fields= thd->count_cuted_fields; /* Set the truncated column values of thd as warning for alter table. */ - thd->count_cuted_fields = CHECK_FIELD_WARN; + Check_level_instant_set check_level_save(thd, CHECK_FIELD_WARN); int res= mysql_inplace_alter_table(thd, table_list, table, &altered_table, &ha_alter_info, &target_mdl_request, &alter_ctx); - thd->count_cuted_fields= save_count_cuted_fields; my_free(const_cast<uchar*>(frm.str)); if (res) diff --git a/sql/sql_tvc.cc b/sql/sql_tvc.cc index 763fd8ec45b..916047c4b0f 100644 --- a/sql/sql_tvc.cc +++ b/sql/sql_tvc.cc @@ -828,7 +828,8 @@ static bool cmp_row_types(Item* item1, Item* item2) Item *inner= item1->element_index(i); Item *outer= item2->element_index(i); if (!inner->type_handler()->subquery_type_allows_materialization(inner, - outer)) + outer, + true)) return true; } return false; @@ -894,7 +895,7 @@ Item *Item_func_in::in_predicate_to_in_subs_transformer(THD *thd, for (uint i=1; i < arg_count; i++) { - if (!args[i]->const_item() || cmp_row_types(args[0], args[i])) + if (!args[i]->const_item() || cmp_row_types(args[i], args[0])) return this; } @@ -974,6 +975,7 @@ Item *Item_func_in::in_predicate_to_in_subs_transformer(THD *thd, if (!(in_subs= new (thd->mem_root) Item_in_subselect(thd, args[0], sq_select))) goto err; + in_subs->converted_from_in_predicate= TRUE; sq= in_subs; if (negated) sq= negate_expression(thd, in_subs); diff --git a/sql/sql_type.cc b/sql/sql_type.cc index ad356b4c874..36f128a3a0b 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -19,6 +19,7 @@ #include "sql_const.h" #include "sql_class.h" #include "sql_time.h" +#include "sql_string.h" #include "item.h" #include "log.h" #include "tztime.h" @@ -6683,7 +6684,8 @@ uint Type_handler_timestamp_common::Item_decimal_precision(const Item *item) con bool Type_handler_real_result:: subquery_type_allows_materialization(const Item *inner, - const Item *outer) const + const Item *outer, + bool is_in_predicate) const { DBUG_ASSERT(inner->cmp_type() == REAL_RESULT); return outer->cmp_type() == REAL_RESULT; @@ -6692,7 +6694,8 @@ bool Type_handler_real_result:: bool Type_handler_int_result:: subquery_type_allows_materialization(const Item *inner, - const Item *outer) const + const Item *outer, + bool is_in_predicate) const { DBUG_ASSERT(inner->cmp_type() == INT_RESULT); return outer->cmp_type() == INT_RESULT; @@ -6701,7 +6704,8 @@ bool Type_handler_int_result:: bool Type_handler_decimal_result:: subquery_type_allows_materialization(const Item *inner, - const Item *outer) const + const Item *outer, + bool is_in_predicate) const { DBUG_ASSERT(inner->cmp_type() == DECIMAL_RESULT); return outer->cmp_type() == DECIMAL_RESULT; @@ -6710,23 +6714,37 @@ bool Type_handler_decimal_result:: bool Type_handler_string_result:: subquery_type_allows_materialization(const Item *inner, - const Item *outer) const + const Item *outer, + bool is_in_predicate) const { DBUG_ASSERT(inner->cmp_type() == STRING_RESULT); - return outer->cmp_type() == STRING_RESULT && - outer->collation.collation == inner->collation.collation && - /* - Materialization also is unable to work when create_tmp_table() will - create a blob column because item->max_length is too big. - The following test is copied from varstring_type_handler(). - */ - !inner->too_big_for_varchar(); + if (outer->cmp_type() == STRING_RESULT && + /* + Materialization also is unable to work when create_tmp_table() will + create a blob column because item->max_length is too big. + The following test is copied from varstring_type_handler(). + */ + !inner->too_big_for_varchar()) + { + if (outer->collation.collation == inner->collation.collation) + return true; + if (is_in_predicate) + { + Charset inner_col(inner->collation.collation); + if (inner_col.encoding_allows_reinterpret_as(outer-> + collation.collation) && + inner_col.eq_collation_specific_names(outer->collation.collation)) + return true; + } + } + return false; } bool Type_handler_temporal_result:: subquery_type_allows_materialization(const Item *inner, - const Item *outer) const + const Item *outer, + bool is_in_predicate) const { DBUG_ASSERT(inner->cmp_type() == TIME_RESULT); return mysql_timestamp_type() == diff --git a/sql/sql_type.h b/sql/sql_type.h index 939c651233c..f8ebc269788 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -3718,9 +3718,21 @@ public: Item *target_expr, Item *target_value, Item_bool_func2 *source, Item *source_expr, Item *source_const) const= 0; + + /* + @brief + Check if an IN subquery allows materialization or not + @param + inner expression on the inner side of the IN subquery + outer expression on the outer side of the IN subquery + is_in_predicate SET to true if IN subquery was converted from an + IN predicate or we are checking if materialization + strategy can be used for an IN predicate + */ virtual bool subquery_type_allows_materialization(const Item *inner, - const Item *outer) const= 0; + const Item *outer, + bool is_in_predicate) const= 0; /** Make a simple constant replacement item for a constant "src", so the new item can futher be used for comparison with "cmp", e.g.: @@ -3966,7 +3978,8 @@ public: return 0; } bool subquery_type_allows_materialization(const Item *inner, - const Item *outer) const + const Item *outer, + bool is_in_predicate) const { DBUG_ASSERT(0); return false; @@ -4313,7 +4326,8 @@ public: const Field *field) const; int stored_field_cmp_to_item(THD *thd, Field *field, Item *item) const; bool subquery_type_allows_materialization(const Item *inner, - const Item *outer) const; + const Item *outer, + bool is_in_predicate) const; void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, Sort_param *param) const; void sortlength(THD *thd, @@ -4399,7 +4413,8 @@ public: return item_val.is_null() ? 0 : my_decimal(field).cmp(item_val.ptr()); } bool subquery_type_allows_materialization(const Item *inner, - const Item *outer) const; + const Item *outer, + bool is_in_predicate) const; Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const; void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, Sort_param *param) const; @@ -4624,7 +4639,8 @@ public: const Type_handler *type_handler_for_comparison() const; int stored_field_cmp_to_item(THD *thd, Field *field, Item *item) const; bool subquery_type_allows_materialization(const Item *inner, - const Item *outer) const; + const Item *outer, + bool is_in_predicate) const; Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const; void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, Sort_param *param) const; @@ -4733,7 +4749,8 @@ public: Item_bool_func2 *source, Item *source_expr, Item *source_const) const; bool subquery_type_allows_materialization(const Item *inner, - const Item *outer) const; + const Item *outer, + bool is_in_predicate) const; bool Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func, Item **items, uint nitems) const; bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const; @@ -4855,7 +4872,8 @@ public: Item_bool_func2 *source, Item *source_expr, Item *source_const) const; bool subquery_type_allows_materialization(const Item *inner, - const Item *outer) const; + const Item *outer, + bool is_in_predicate) const; Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const; bool set_comparator_func(Arg_comparator *cmp) const; @@ -6185,7 +6203,8 @@ public: return blob_type_handler(item); } bool subquery_type_allows_materialization(const Item *inner, - const Item *outer) const + const Item *outer, + bool is_in_predicate) const { return false; // Materialization does not work with BLOB columns } @@ -6304,7 +6323,8 @@ public: return true; } bool subquery_type_allows_materialization(const Item *inner, - const Item *outer) const + const Item *outer, + bool is_in_predicate) const { return false; // Materialization does not work with GEOMETRY columns } diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 994e3665267..027d5882722 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -2102,6 +2102,7 @@ bool st_select_lex::cleanup() delete join; join= 0; } + leaf_tables.empty(); for (SELECT_LEX_UNIT *lex_unit= first_inner_unit(); lex_unit ; lex_unit= lex_unit->next_unit()) { diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 8e3b49bb6f7..4c3028b0a00 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -4123,7 +4123,7 @@ static bool fix_autocommit(sys_var *self, THD *thd, enum_var_type type) if (trans_commit_stmt(thd) || trans_commit(thd)) { thd->variables.option_bits&= ~OPTION_AUTOCOMMIT; - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); WSREP_DEBUG("autocommit, MDL TRX lock released: %lld", (longlong) thd->thread_id); return true; diff --git a/sql/table.cc b/sql/table.cc index 38777de34a7..084b441e4c6 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -8499,7 +8499,7 @@ int TABLE::period_make_insert(Item *src, Field *dst) { THD *thd= in_use; - file->store_auto_increment(); + ulonglong prev_insert_id= file->next_insert_id; store_record(this, record[1]); int res= src->save_in_field(dst, true); @@ -8519,7 +8519,7 @@ int TABLE::period_make_insert(Item *src, Field *dst) restore_record(this, record[1]); if (res) - file->restore_auto_increment(); + file->restore_auto_increment(prev_insert_id); return res; } diff --git a/sql/threadpool_common.cc b/sql/threadpool_common.cc index f40a958e62a..3320b9fc0cc 100644 --- a/sql/threadpool_common.cc +++ b/sql/threadpool_common.cc @@ -209,12 +209,11 @@ void tp_callback(TP_connection *c) error: c->thd= 0; - delete c; - if (thd) { threadpool_remove_connection(thd); } + delete c; worker_context.restore(); } diff --git a/sql/transaction.cc b/sql/transaction.cc index aecee04c364..135d274e6c6 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -138,7 +138,7 @@ bool trans_begin(THD *thd, uint flags) Release transactional metadata locks only after the transaction has been committed. */ - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); // The RO/RW options are mutually exclusive. DBUG_ASSERT(!((flags & MYSQL_START_TRANS_OPT_READ_ONLY) && diff --git a/sql/unireg.cc b/sql/unireg.cc index 41481d253ee..17222efe791 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -1028,7 +1028,6 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options, TABLE table; TABLE_SHARE share; Create_field *field; - enum_check_fields old_count_cuted_fields= thd->count_cuted_fields; DBUG_ENTER("make_empty_rec"); /* We need a table to generate columns for default values */ @@ -1047,7 +1046,7 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options, null_pos= buff; List_iterator<Create_field> it(create_fields); - thd->count_cuted_fields= CHECK_FIELD_WARN; // To find wrong default values + Check_level_instant_set check_level_save(thd, CHECK_FIELD_WARN); while ((field=it++)) { Record_addr addr(buff + field->offset + data_offset, @@ -1094,6 +1093,5 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options, *(null_pos + null_count / 8)|= ~(((uchar) 1 << (null_count & 7)) - 1); err: - thd->count_cuted_fields= old_count_cuted_fields; DBUG_RETURN(error); } /* make_empty_rec */ diff --git a/sql/xa.cc b/sql/xa.cc index de7fdf51011..6275532e035 100644 --- a/sql/xa.cc +++ b/sql/xa.cc @@ -513,11 +513,13 @@ bool trans_xa_prepare(THD *thd) /** Commit and terminate the a XA transaction. + Transactional locks are released if transaction ended @param thd Current thread @retval FALSE Success @retval TRUE Failure + */ bool trans_xa_commit(THD *thd) @@ -601,6 +603,7 @@ bool trans_xa_commit(THD *thd) xid_cache_delete(thd, &thd->transaction.xid_state); trans_track_end_trx(thd); + thd->mdl_context.release_transactional_locks(); DBUG_RETURN(res); } @@ -608,6 +611,7 @@ bool trans_xa_commit(THD *thd) /** Roll back and terminate a XA transaction. + Transactional locks are released if transaction ended @param thd Current thread |