1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-07-29 08:21:15 +03:00

MCOL-4868 UPDATE on a ColumnStore table containing an IN-subquery

on a non-ColumnStore table does not work.

As part of MCOL-4617, we moved the in-to-exists predicate creation
and injection from the server into the engine. However, when query
with an IN Subquery contains a non-ColumnStore table, the server
still performs the in-to-exists predicate transformation for the
foreign engine table. This caused ColumnStore's execution plan to
contain incorrect WHERE predicates. As a fix, we call
mutate_optimizer_flags() for the WRITE lock, in addition to the READ
table lock. And in mutate_optimizer_flags(), we change the optimizer
flag from OPTIMIZER_SWITCH_IN_TO_EXISTS to OPTIMIZER_SWITCH_MATERIALIZATION.
This commit is contained in:
Gagan Goel
2021-12-14 19:25:03 -05:00
parent 6144e6ff99
commit 7f456e58cc
6 changed files with 209 additions and 12 deletions

View File

@ -6546,7 +6546,7 @@ bool isForeignTableUpdate(THD* thd)
{
LEX* lex = thd->lex;
if (lex->sql_command != SQLCOM_UPDATE_MULTI)
if (!isUpdateStatement(lex->sql_command))
return false;
Item_field* item;
@ -6561,6 +6561,40 @@ bool isForeignTableUpdate(THD* thd)
return false;
}
bool isMCSTableUpdate(THD* thd)
{
LEX* lex = thd->lex;
if (!isUpdateStatement(lex->sql_command))
return false;
Item_field* item;
List_iterator_fast<Item> field_it(lex->first_select_lex()->item_list);
while ((item = (Item_field*) field_it++))
{
if (item->field && item->field->table && isMCSTable(item->field->table))
return true;
}
return false;
}
bool isMCSTableDelete(THD* thd)
{
LEX* lex = thd->lex;
if (!isDeleteStatement(lex->sql_command))
return false;
TABLE_LIST* table_ptr = lex->first_select_lex()->get_table_list();
if (table_ptr && table_ptr->table && isMCSTable(table_ptr->table))
return true;
return false;
}
// This function is different from isForeignTableUpdate()
// above as it only checks if any of the tables involved
// in the multi-table update statement is a foreign table,
@ -6570,7 +6604,7 @@ bool isUpdateHasForeignTable(THD* thd)
{
LEX* lex = thd->lex;
if (lex->sql_command != SQLCOM_UPDATE_MULTI)
if (!isUpdateStatement(lex->sql_command))
return false;
TABLE_LIST* table_ptr = lex->first_select_lex()->get_table_list();

View File

@ -2580,7 +2580,7 @@ int ha_mcs_impl_rnd_next(uchar* buf, TABLE* table)
thd->lex->sql_command == SQLCOM_LOAD))
return HA_ERR_END_OF_FILE;
if (isUpdateOrDeleteStatement(thd->lex->sql_command, !isForeignTableUpdate(thd)))
if (isMCSTableUpdate(thd) || isMCSTableDelete(thd))
return HA_ERR_END_OF_FILE;
// @bug 2547
@ -2674,7 +2674,7 @@ int ha_mcs_impl_rnd_end(TABLE* table, bool is_pushdown_hand)
if ( (thd->lex)->sql_command == SQLCOM_ALTER_TABLE )
return rc;
if (isUpdateOrDeleteStatement(thd->lex->sql_command, !isForeignTableUpdate(thd)))
if (isMCSTableUpdate(thd) || isMCSTableDelete(thd))
return rc;
if (!ci)
@ -4010,7 +4010,7 @@ int ha_mcs::impl_external_lock(THD* thd, TABLE* table, int lock_type)
}
else
{
if (lock_type == 0)
if ((lock_type == 0) || (lock_type == 1))
{
ci->physTablesList.insert(table);
// MCOL-2178 Disable Conversion of Big IN Predicates Into Subqueries
@ -4538,7 +4538,7 @@ int ha_mcs_impl_group_by_next(TABLE* table)
thd->lex->sql_command == SQLCOM_LOAD))
return HA_ERR_END_OF_FILE;
if (isUpdateOrDeleteStatement(thd->lex->sql_command, !isForeignTableUpdate(thd)))
if (isMCSTableUpdate(thd) || isMCSTableDelete(thd))
return HA_ERR_END_OF_FILE;
if (get_fe_conn_info_ptr() == nullptr)

View File

@ -368,6 +368,8 @@ const std::string bestTableName(const Item_field* ifp);
bool isMCSTable(TABLE* table_ptr);
bool isForeignTableUpdate(THD* thd);
bool isUpdateHasForeignTable(THD* thd);
bool isMCSTableUpdate(THD* thd);
bool isMCSTableDelete(THD* thd);
// execution plan util functions prototypes
execplan::ReturnedColumn* buildReturnedColumn(Item* item, gp_walk_info& gwi, bool& nonSupport, bool isRefItem = false);
@ -411,10 +413,10 @@ bool buildEqualityPredicate(execplan::ReturnedColumn* lhs,
const std::vector<Item*>& itemList,
bool isInSubs = false);
inline bool isUpdateStatement(const enum_sql_command& command, const bool isMCSTableUpdate = true)
inline bool isUpdateStatement(const enum_sql_command& command)
{
return (command == SQLCOM_UPDATE) ||
(command == SQLCOM_UPDATE_MULTI && isMCSTableUpdate);
return ((command == SQLCOM_UPDATE) ||
(command == SQLCOM_UPDATE_MULTI));
}
inline bool isDeleteStatement(const enum_sql_command& command)
@ -423,9 +425,9 @@ inline bool isDeleteStatement(const enum_sql_command& command)
(command == SQLCOM_DELETE_MULTI);
}
inline bool isUpdateOrDeleteStatement(const enum_sql_command& command, const bool isMCSTableUpdate = true)
inline bool isUpdateOrDeleteStatement(const enum_sql_command& command)
{
return isUpdateStatement(command, isMCSTableUpdate) ||
return isUpdateStatement(command) ||
isDeleteStatement(command);
}

View File

@ -36,7 +36,7 @@ void mutate_optimizer_flags(THD *thd_)
// CS restores it later in SH::scan_end() and in case of an error
// in SH::scan_init()
ulonglong flags_to_set = OPTIMIZER_SWITCH_IN_TO_EXISTS |
ulonglong flags_to_set = OPTIMIZER_SWITCH_MATERIALIZATION |
OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED |
OPTIMIZER_SWITCH_COND_PUSHDOWN_FROM_HAVING;