summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2020-12-03 08:12:47 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2020-12-03 08:12:47 +0200
commita13fac9eeef0f304b6b6f52ad2b6659f22190523 (patch)
tree7bbcbe8765354f03142a005198276cadbfac6b20 /sql
parente28d9c15c3093612d841b24b5bb6b480c9b8009c (diff)
parentf146969fb3a1e8ed508f55ee38faaffd5cff2021 (diff)
downloadmariadb-git-a13fac9eeef0f304b6b6f52ad2b6659f22190523.tar.gz
Merge 10.5 into 10.6
Diffstat (limited to 'sql')
-rw-r--r--sql/ha_partition.cc2
-rw-r--r--sql/ha_partition.h20
-rw-r--r--sql/handler.cc9
-rw-r--r--sql/handler.h15
-rw-r--r--sql/item.cc8
-rw-r--r--sql/item.h7
-rw-r--r--sql/item_cmpfunc.cc11
-rw-r--r--sql/item_subselect.cc3
-rw-r--r--sql/item_subselect.h8
-rw-r--r--sql/log_event_server.cc9
-rw-r--r--sql/mdl.cc6
-rw-r--r--sql/mdl.h2
-rw-r--r--sql/opt_subselect.cc8
-rw-r--r--sql/rpl_gtid.cc6
-rw-r--r--sql/rpl_injector.cc56
-rw-r--r--sql/rpl_rli.cc14
-rw-r--r--sql/sp.cc6
-rw-r--r--sql/sp_head.cc8
-rw-r--r--sql/sql_acl.cc2
-rw-r--r--sql/sql_admin.cc20
-rw-r--r--sql/sql_base.cc5
-rw-r--r--sql/sql_class.cc4
-rw-r--r--sql/sql_class.h7
-rw-r--r--sql/sql_delete.cc4
-rw-r--r--sql/sql_derived.cc19
-rw-r--r--sql/sql_insert.cc15
-rw-r--r--sql/sql_lex.cc41
-rw-r--r--sql/sql_parse.cc30
-rw-r--r--sql/sql_prepare.cc2
-rw-r--r--sql/sql_select.cc4
-rw-r--r--sql/sql_select.h11
-rw-r--r--sql/sql_show.cc21
-rw-r--r--sql/sql_statistics.cc4
-rw-r--r--sql/sql_table.cc4
-rw-r--r--sql/sql_tvc.cc10
-rw-r--r--sql/sql_type.cc44
-rw-r--r--sql/sql_type.h45
-rw-r--r--sql/sql_type_geom.h4
-rw-r--r--sql/sql_union.cc1
-rw-r--r--sql/sys_vars.cc2
-rw-r--r--sql/table.cc4
-rw-r--r--sql/transaction.cc2
-rw-r--r--sql/unireg.cc4
-rw-r--r--sql/wsrep_client_service.cc2
-rw-r--r--sql/wsrep_high_priority_service.cc6
-rw-r--r--sql/wsrep_mysqld.cc2
-rw-r--r--sql/wsrep_schema.cc2
-rw-r--r--sql/wsrep_server_service.cc2
-rw-r--r--sql/wsrep_storage_service.cc4
-rw-r--r--sql/xa.cc10
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;
}