diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2020-12-03 08:12:47 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2020-12-03 08:12:47 +0200 |
commit | a13fac9eeef0f304b6b6f52ad2b6659f22190523 (patch) | |
tree | 7bbcbe8765354f03142a005198276cadbfac6b20 /sql | |
parent | e28d9c15c3093612d841b24b5bb6b480c9b8009c (diff) | |
parent | f146969fb3a1e8ed508f55ee38faaffd5cff2021 (diff) | |
download | mariadb-git-a13fac9eeef0f304b6b6f52ad2b6659f22190523.tar.gz |
Merge 10.5 into 10.6
Diffstat (limited to 'sql')
50 files changed, 297 insertions, 238 deletions
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 7f00a194698..470f59fe15f 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -4443,7 +4443,7 @@ int ha_partition::write_row(const uchar * buf) DBUG_ASSERT(!m_file[part_id]->row_logging); 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); exit: diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 8d0557f4ae4..3c3e394d59f 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) { @@ -429,24 +427,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 01825c13da6..314fe7acb8c 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -3514,7 +3514,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"); /* @@ -3656,10 +3655,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 cb55887ef6f..66ff4db8050 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -3278,9 +3278,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), @@ -3308,7 +3305,7 @@ public: m_psi_numrows(0), m_psi_locker(NULL), row_logging(0), row_logging_init(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", @@ -4028,16 +4025,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 dc90b9fe1b3..2bf53dc885b 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1442,16 +1442,12 @@ 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); + Check_level_instant_set check_level_save(thd, CHECK_FIELD_IGNORE); Sql_mode_save sms(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); return res; } diff --git a/sql/item.h b/sql/item.h index fb480b4c578..677112e448c 100644 --- a/sql/item.h +++ b/sql/item.h @@ -973,6 +973,13 @@ 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; + common_flags= static_cast<uint8> + ((common_flags & ~IS_AUTO_GENERATED_NAME) | + (item->common_flags & IS_AUTO_GENERATED_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 83eb605f463..bfd415344ef 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -321,19 +321,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 @@ -370,8 +369,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 cbde9599073..7916bcb45a9 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1520,7 +1520,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 ec4398b9a76..a346def72f1 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -613,12 +613,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() override; subs_type substype() override { return IN_SUBS; } void reset() override diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index 5a97f4c81b1..cd35c6d6d23 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -2987,10 +2987,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(); @@ -4038,7 +4038,7 @@ int Xid_log_event::do_commit() { bool res; res= trans_commit(thd); /* Automatically rolls back on error. */ - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); return res; } #endif @@ -4087,10 +4087,7 @@ int XA_prepare_log_event::do_commit() res= trans_xa_prepare(thd); } else - { res= trans_xa_commit(thd); - thd->mdl_context.release_transactional_locks(); - } return res; } diff --git a/sql/mdl.cc b/sql/mdl.cc index 4772dc017f9..5f5e5c3ce9a 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -3039,15 +3039,17 @@ void MDL_context::rollback_to_savepoint(const MDL_savepoint &mdl_savepoint) implementation of COMMIT (implicit or explicit) and ROLLBACK. */ -void MDL_context::release_transactional_locks() +void MDL_context::release_transactional_locks(THD *thd) { DBUG_ENTER("MDL_context::release_transactional_locks"); + /* Fail if there are active transactions */ + DBUG_ASSERT(!(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; } - void MDL_context::release_statement_locks() { DBUG_ENTER("MDL_context::release_transactional_locks"); diff --git a/sql/mdl.h b/sql/mdl.h index f6b7154fba0..9dbf9aa7f4f 100644 --- a/sql/mdl.h +++ b/sql/mdl.h @@ -921,7 +921,7 @@ public: void set_lock_duration(MDL_ticket *mdl_ticket, enum_mdl_duration duration); void release_statement_locks(); - void release_transactional_locks(); + void release_transactional_locks(THD *thd); void release_explicit_locks(); void rollback_to_savepoint(const MDL_savepoint &mdl_savepoint); diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index b7f5ffd02d1..96a35e10bf2 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -872,6 +872,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= left_exp->element_index(i); @@ -879,8 +880,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 af0c4747d2b..bc06188af34 100644 --- a/sql/rpl_gtid.cc +++ b/sql/rpl_gtid.cc @@ -445,7 +445,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(); } return err; } @@ -736,7 +736,7 @@ end: if (in_transaction) thd->mdl_context.release_statement_locks(); else - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); } thd->lex->restore_backup_query_tables_list(&lex_backup); thd->variables.option_bits= thd_saved_option; @@ -991,7 +991,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 0726697211b..2319f69d67c 100644 --- a/sql/rpl_injector.cc +++ b/sql/rpl_injector.cc @@ -69,34 +69,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 b7127d86fcd..8b61a3a708b 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -1677,7 +1677,7 @@ end: { *out_hton= table->s->db_type(); close_thread_tables(thd); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); } return err; } @@ -1704,7 +1704,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 @@ -1717,7 +1717,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; @@ -2003,7 +2003,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; @@ -2292,7 +2292,7 @@ void rpl_group_info::cleanup_context(THD *thd, bool error) if (thd->transaction->xid_state.is_explicit_XA()) xa_trans_force_rollback(thd); - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); if (thd == rli->sql_driver_thd) { @@ -2406,10 +2406,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 3737bd11740..abd89dde499 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1205,8 +1205,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", @@ -1240,8 +1238,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))) { @@ -1500,7 +1497,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 9e5b5bee0f2..513e7207b7e 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -2390,10 +2390,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(); } @@ -3518,10 +3518,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 bad39cfc1d1..25e8aa42c7c 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -9463,6 +9463,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 2d6f891f56f..7c1f8596ece 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -42,7 +42,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 @@ -115,7 +115,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. @@ -278,7 +278,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); } @@ -607,7 +607,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(); MDL_REQUEST_INIT(&table->mdl_request, MDL_key::TABLE, table->db.str, table->table_name.str, MDL_SHARED_NO_READ_WRITE, MDL_TRANSACTION); @@ -668,7 +668,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 @@ -735,7 +735,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 @@ -868,7 +868,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(); MDL_REQUEST_INIT(&table->mdl_request, MDL_key::TABLE, table->db.str, table->table_name.str, MDL_SHARED_NO_READ_WRITE, MDL_TRANSACTION); @@ -1099,7 +1099,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; @@ -1258,7 +1258,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 @@ -1296,7 +1296,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 dec5bd91f36..d02d130c084 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -9040,9 +9040,12 @@ void close_mysql_tables(THD *thd) { if (! thd->in_sub_stmt) + { trans_commit_stmt(thd); + trans_commit(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 167b2d20023..1cc9a6a61d3 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1565,7 +1565,7 @@ void THD::cleanup(void) and left the mode a few lines above), there will be outstanding metadata locks. Release them. */ - mdl_context.release_transactional_locks(); + mdl_context.release_transactional_locks(this); backup_end(this); backup_unlock(this); @@ -4919,7 +4919,7 @@ void destroy_background_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 65b2a275632..6bd08343c9e 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -4772,6 +4772,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(this); + } int decide_logging_format(TABLE_LIST *tables); /* In Some cases when decide_logging_format is called it does not have all diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 35aa306c88c..f3472cac330 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -248,7 +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(); + 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); @@ -264,7 +264,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 428e7b1d261..a9155f361b5 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -1401,7 +1401,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); @@ -1460,6 +1461,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()) { @@ -1480,7 +1495,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 7833059438e..1e456a724e7 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1769,7 +1769,7 @@ int write_record(THD *thd, TABLE *table, COPY_INFO *info, select_result *sink) 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"); @@ -1918,7 +1918,7 @@ int write_record(THD *thd, TABLE *table, COPY_INFO *info, select_result *sink) 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) { @@ -2110,7 +2110,7 @@ int write_record(THD *thd, TABLE *table, COPY_INFO *info, select_result *sink) 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 after_trg_or_ignored_err; } @@ -2143,7 +2143,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); @@ -2297,7 +2297,7 @@ public: if (table) { close_thread_tables(&thd); - thd.mdl_context.release_transactional_locks(); + thd.mdl_context.release_transactional_locks(&thd); } mysql_mutex_destroy(&mutex); mysql_cond_destroy(&cond); @@ -3130,7 +3130,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; } @@ -3356,7 +3356,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 @@ -4971,6 +4971,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_lex.cc b/sql/sql_lex.cc index ce3bf902931..dc5449d0ab4 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -3567,8 +3567,10 @@ void LEX::print(String *str, enum_query_type query_type) str->append(STRING_WITH_LEN("UPDATE ")); if (ignore) str->append(STRING_WITH_LEN("IGNORE ")); - // table name - str->append(query_tables->alias); + // table name. If the query was using a view, we need + // the underlying table name, not the view name + TABLE_LIST *base_tbl= query_tables->table->pos_in_table_list; + base_tbl->print(thd, table_map(0), str, query_type); str->append(STRING_WITH_LEN(" SET ")); // print item assignments List_iterator<Item> it(sel->item_list); @@ -3608,6 +3610,41 @@ void LEX::print(String *str, enum_query_type query_type) sel->select_limit->print(str, query_type); } } + else if (sql_command == SQLCOM_DELETE) + { + SELECT_LEX *sel= first_select_lex(); + str->append(STRING_WITH_LEN("DELETE ")); + if (ignore) + str->append(STRING_WITH_LEN("IGNORE ")); + + str->append(STRING_WITH_LEN("FROM ")); + // table name. If the query was using a view, we need + // the underlying table name, not the view name + TABLE_LIST *base_tbl= query_tables->table->pos_in_table_list; + base_tbl->print(thd, table_map(0), str, query_type); + + if (sel->where) + { + str->append(STRING_WITH_LEN(" WHERE ")); + sel->where->print(str, query_type); + } + + if (sel->order_list.elements) + { + str->append(STRING_WITH_LEN(" ORDER BY ")); + for (ORDER *ord= sel->order_list.first; ord; ord= ord->next) + { + if (ord != sel->order_list.first) + str->append(STRING_WITH_LEN(", ")); + (*ord->item)->print(str, query_type); + } + } + if (sel->select_limit) + { + str->append(STRING_WITH_LEN(" LIMIT ")); + sel->select_limit->print(str, query_type); + } + } else DBUG_ASSERT(0); // Not implemented yet } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 0488b240bb2..b20aa5f766d 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2022,7 +2022,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(); @@ -2087,7 +2087,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); @@ -2122,7 +2122,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; } @@ -2883,7 +2883,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; } @@ -3628,7 +3628,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", @@ -4939,7 +4939,7 @@ mysql_execute_command(THD *thd) res= trans_commit_implicit(thd); if (thd->locked_tables_list.unlock_locked_tables(thd)) res= 1; - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); thd->variables.option_bits&= ~(OPTION_TABLE_LOCK); thd->reset_binlog_for_next_statement(); } @@ -4956,7 +4956,7 @@ mysql_execute_command(THD *thd) if (thd->locked_tables_list.unlock_locked_tables(thd)) res= 1; /* Release transactional metadata locks. */ - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); if (res) goto error; @@ -5472,7 +5472,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); @@ -5491,7 +5491,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", @@ -5529,7 +5529,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) { @@ -5716,7 +5716,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", @@ -5734,7 +5733,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", @@ -5945,7 +5943,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)) { @@ -5959,7 +5957,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()) @@ -5974,7 +5972,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) { @@ -5999,7 +5997,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 aac742bb82c..285846558d2 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -4302,7 +4302,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 73d7a7d25de..bf3d4fd9bb1 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -24232,8 +24232,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; @@ -24245,7 +24244,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 2aba63ddc79..f39a70cc3e1 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1902,18 +1902,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 0f6200ff237..ca3e2aaa97e 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -3671,7 +3671,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"); @@ -3794,7 +3793,6 @@ static bool show_status_array(THD *thd, const char *wild, } } end: - thd->count_cuted_fields= save_count_cuted_fields; DBUG_RETURN(res); } @@ -4521,8 +4519,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; @@ -5037,12 +5034,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; @@ -8493,13 +8487,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]); @@ -8533,7 +8520,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, @@ -8696,6 +8682,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 2636299e330..7b600bd45c4 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -2899,7 +2899,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"); @@ -2915,7 +2914,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; @@ -2997,7 +2996,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 c2ba9bcadfb..b8c51f05f77 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -10636,16 +10636,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 df774a5d8dd..5f732d474f8 100644 --- a/sql/sql_tvc.cc +++ b/sql/sql_tvc.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, MariaDB +/* Copyright (c) 2017, 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 @@ -861,7 +861,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; @@ -941,8 +942,8 @@ Item *Item_func_in::in_predicate_to_in_subs_transformer(THD *thd, trace_conv.add("reason", "non-constant element in the IN-list"); return this; } - - if (cmp_row_types(args[0], args[i])) + + if (cmp_row_types(args[i], args[0])) { trace_conv.add("done", false); trace_conv.add("reason", "type mismatch"); @@ -1027,6 +1028,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 00b9c71cc37..6c5f72c2ce2 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -20,6 +20,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" @@ -7077,7 +7078,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; @@ -7086,7 +7088,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; @@ -7095,7 +7098,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; @@ -7104,23 +7108,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 db4f67e343f..271e74a9762 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -4049,9 +4049,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.: @@ -4311,8 +4323,8 @@ public: DBUG_ASSERT(0); return 0; } - bool subquery_type_allows_materialization(const Item *inner, - const Item *outer) const override + bool subquery_type_allows_materialization(const Item *, const Item *, + bool) const override { DBUG_ASSERT(0); return false; @@ -4714,7 +4726,8 @@ public: int stored_field_cmp_to_item(THD *thd, Field *field, Item *item) const override; bool subquery_type_allows_materialization(const Item *inner, - const Item *outer) + const Item *outer, + bool is_in_predicate) const override; void make_sort_key_part(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, @@ -4819,7 +4832,9 @@ 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 override; + const Item *outer, + bool is_in_predicate) + const override; Field *make_schema_field(MEM_ROOT *root, TABLE *table, const Record_addr &addr, @@ -5073,7 +5088,9 @@ public: const Type_handler *type_handler_for_comparison() const override; int stored_field_cmp_to_item(THD *thd, Field *field, Item *item) const override; bool subquery_type_allows_materialization(const Item *inner, - const Item *outer) const override; + const Item *outer, + bool is_in_predicate) + const override; Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const override; Field *make_table_field(MEM_ROOT *root, const LEX_CSTRING *name, @@ -5214,7 +5231,9 @@ public: Item *source_expr, Item *source_const) const override; bool subquery_type_allows_materialization(const Item *inner, - const Item *outer) const override; + const Item *outer, + bool is_in_predicate) + const override; bool Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func, Item **items, uint nitems) const override; @@ -5352,7 +5371,9 @@ public: Item *source_expr, Item *source_const) const override; bool subquery_type_allows_materialization(const Item *inner, - const Item *outer) const override; + const Item *outer, + bool is_in_predicate) + const override; Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const override; Item_cache *Item_get_cache(THD *thd, const Item *item) const override; @@ -6983,8 +7004,8 @@ public: { return blob_type_handler(item); } - bool subquery_type_allows_materialization(const Item *inner, - const Item *outer) const override + bool subquery_type_allows_materialization(const Item *, const Item *, bool) + const override { return false; // Materialization does not work with BLOB columns } @@ -7114,7 +7135,7 @@ public: { return MYSQL_TYPE_BLOB_COMPRESSED; } - ulong KEY_pack_flags(uint column_nr) const override + ulong KEY_pack_flags(uint) const override { DBUG_ASSERT(0); return 0; @@ -7125,7 +7146,7 @@ public: Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; - enum_dynamic_column_type dyncol_type(const Type_all_attributes *attr) + enum_dynamic_column_type dyncol_type(const Type_all_attributes *) const override { DBUG_ASSERT(0); diff --git a/sql/sql_type_geom.h b/sql/sql_type_geom.h index 74290e47afe..a2933114751 100644 --- a/sql/sql_type_geom.h +++ b/sql/sql_type_geom.h @@ -67,8 +67,8 @@ public: geometry_type() == th->geometry_type(); } bool type_can_have_key_part() const override { return true; } - bool subquery_type_allows_materialization(const Item *inner, - const Item *outer) const override + bool subquery_type_allows_materialization(const Item *, const Item *, bool) + const override { return false; // Materialization does not work with GEOMETRY columns } diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 9e51bb43a74..6da1175e709 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -2747,6 +2747,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 64040243df0..d0eff0adada 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -4325,7 +4325,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 c48a6fed89a..6cd2b1690cf 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -8741,7 +8741,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); @@ -8761,7 +8761,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/transaction.cc b/sql/transaction.cc index 421aa1cfc51..8bd58419ec9 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -151,7 +151,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 ecd5bb8d430..bffe51b6c49 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -1151,7 +1151,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 */ @@ -1170,7 +1169,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, @@ -1217,6 +1216,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/wsrep_client_service.cc b/sql/wsrep_client_service.cc index c01c256e872..24e1e198507 100644 --- a/sql/wsrep_client_service.cc +++ b/sql/wsrep_client_service.cc @@ -345,7 +345,7 @@ int Wsrep_client_service::bf_rollback() { m_thd->global_read_lock.unlock_global_read_lock(m_thd); } - m_thd->mdl_context.release_transactional_locks(); + m_thd->release_transactional_locks(); m_thd->mdl_context.release_explicit_locks(); DBUG_RETURN(ret); diff --git a/sql/wsrep_high_priority_service.cc b/sql/wsrep_high_priority_service.cc index 5961a9574eb..3116315b9c7 100644 --- a/sql/wsrep_high_priority_service.cc +++ b/sql/wsrep_high_priority_service.cc @@ -290,7 +290,7 @@ int Wsrep_high_priority_service::append_fragment_and_commit( ret= ret || trans_commit(m_thd); ret= ret || (m_thd->wsrep_cs().after_applying(), 0); - m_thd->mdl_context.release_transactional_locks(); + m_thd->release_transactional_locks(); free_root(m_thd->mem_root, MYF(MY_KEEP_PREALLOC)); @@ -332,7 +332,7 @@ int Wsrep_high_priority_service::commit(const wsrep::ws_handle& ws_handle, m_rgi->cleanup_context(thd, 0); } - m_thd->mdl_context.release_transactional_locks(); + m_thd->release_transactional_locks(); thd_proc_info(thd, "wsrep applier committed"); @@ -378,7 +378,7 @@ int Wsrep_high_priority_service::rollback(const wsrep::ws_handle& ws_handle, assert(ws_handle == wsrep::ws_handle()); } int ret= (trans_rollback_stmt(m_thd) || trans_rollback(m_thd)); - m_thd->mdl_context.release_transactional_locks(); + m_thd->release_transactional_locks(); m_thd->mdl_context.release_explicit_locks(); free_root(m_thd->mem_root, MYF(MY_KEEP_PREALLOC)); diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 1dfeb782bbe..284df936160 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1267,7 +1267,7 @@ wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* tables, wsrep::key_array* key if (!WSREP(thd) || !WSREP_CLIENT(thd)) return; TABLE_LIST *table; - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); uint counter; MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint(); diff --git a/sql/wsrep_schema.cc b/sql/wsrep_schema.cc index 434f8779544..c7859ac9df3 100644 --- a/sql/wsrep_schema.cc +++ b/sql/wsrep_schema.cc @@ -873,7 +873,7 @@ Wsrep_view Wsrep_schema::restore_view(THD* thd, const Wsrep_id& own_id) const { close_thread_tables(thd); } } - thd->mdl_context.release_transactional_locks(); + thd->release_transactional_locks(); thd->variables.wsrep_sync_wait= wsrep_sync_wait_saved; diff --git a/sql/wsrep_server_service.cc b/sql/wsrep_server_service.cc index 7ba744b4d3c..32b585871d4 100644 --- a/sql/wsrep_server_service.cc +++ b/sql/wsrep_server_service.cc @@ -248,7 +248,7 @@ void Wsrep_server_service::log_view( WSREP_WARN("Failed to commit transaction for store view"); } } - applier->m_thd->mdl_context.release_transactional_locks(); + applier->m_thd->release_transactional_locks(); } /* diff --git a/sql/wsrep_storage_service.cc b/sql/wsrep_storage_service.cc index 2ad817fe25a..4885fd9f7e6 100644 --- a/sql/wsrep_storage_service.cc +++ b/sql/wsrep_storage_service.cc @@ -176,7 +176,7 @@ int Wsrep_storage_service::commit(const wsrep::ws_handle& ws_handle, trans_rollback(m_thd); } m_thd->wsrep_cs().after_applying(); - m_thd->mdl_context.release_transactional_locks(); + m_thd->release_transactional_locks(); DBUG_RETURN(ret); } @@ -191,7 +191,7 @@ int Wsrep_storage_service::rollback(const wsrep::ws_handle& ws_handle, ws_handle, ws_meta, false) || trans_rollback(m_thd)); m_thd->wsrep_cs().after_applying(); - m_thd->mdl_context.release_transactional_locks(); + m_thd->release_transactional_locks(); DBUG_RETURN(ret); } diff --git a/sql/xa.cc b/sql/xa.cc index 15833377fb6..e0defcb92ed 100644 --- a/sql/xa.cc +++ b/sql/xa.cc @@ -404,6 +404,7 @@ bool xa_trans_force_rollback(THD *thd) xid_cache_delete(thd, &thd->transaction->xid_state); trans_track_end_trx(thd); + thd->mdl_context.release_transactional_locks(thd); return rc; } @@ -554,11 +555,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) @@ -718,6 +721,8 @@ bool trans_xa_commit(THD *thd) xid_cache_delete(thd, &xid_state); trans_track_end_trx(thd); + thd->mdl_context.release_transactional_locks(thd); + /* The transaction should be marked as complete in P_S. */ DBUG_ASSERT(thd->m_transaction_psi == NULL || res); DBUG_RETURN(res); @@ -726,6 +731,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 @@ -844,6 +850,10 @@ bool trans_xa_detach(THD *thd) thd->transaction->all.ha_list= 0; thd->transaction->all.no_2pc= 0; thd->m_transaction_psi= 0; + thd->server_status&= ~(SERVER_STATUS_IN_TRANS | + SERVER_STATUS_IN_TRANS_READONLY); + thd->mdl_context.release_transactional_locks(thd); + return false; } |