From 8d0ca554956eddf40dc7f6b552507fa64386e941 Mon Sep 17 00:00:00 2001 From: Gagan Goel Date: Fri, 25 Jun 2021 08:49:53 +0000 Subject: [PATCH] Fixes for queries containing constant scalar subselects in the WHERE clause. For queries of the form: SELECT col1 FROM t1 WHERE col2 = (SELECT 2); We fix the execution plan which earlier had an empty filters expression. For this query, we now build a SimpleFilter with a SimpleColumn and a ConstantColumn as the LHS and the RHS operands respectively. For queries of the form: SELECT ... WHERE col1 NOT IN (SELECT ); The execution plan earlier built a SimpleFilter with an "=" as the predicate operator of the filter. We fix this by assigning the correct "<>" operator instead. --- dbcon/mysql/ha_mcs_execplan.cpp | 39 ++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/dbcon/mysql/ha_mcs_execplan.cpp b/dbcon/mysql/ha_mcs_execplan.cpp index 9cd882762..fef4f9691 100755 --- a/dbcon/mysql/ha_mcs_execplan.cpp +++ b/dbcon/mysql/ha_mcs_execplan.cpp @@ -5388,6 +5388,22 @@ void castTypeArgs(THD* thd, Item_func* ifp, FunctionParm& functionParms) functionParms.push_back(sptp); } +bool isSecondArgumentConstItem(Item_func* ifp) +{ + return (ifp->argument_count() == 2 && + ifp->arguments()[1]->type() == Item::CONST_ITEM); +} + +// SELECT ... WHERE NOT IN (SELECT ); +bool isNotFuncAndConstScalarSubSelect(Item_func* ifp, const std::string& funcName) +{ + return (ifp->with_subquery() && funcName == "not" && + ifp->argument_count() == 1 && + ifp->arguments()[0]->type() == Item::FUNC_ITEM && + std::string(((Item_func*)ifp->arguments()[0])->func_name()) == "=" && + isSecondArgumentConstItem((Item_func*)ifp->arguments()[0])); +} + void gp_walk(const Item* item, void* arg) { gp_walk_info* gwip = reinterpret_cast(arg); @@ -5563,7 +5579,28 @@ void gp_walk(const Item* item, void* arg) ifp->fix_fields(gwip->thd, reinterpret_cast(&ifp)); } - if (ifp->with_subquery() || funcName == "") + // Special handling for queries of the form: + // SELECT ... WHERE col1 NOT IN (SELECT ); + if (isNotFuncAndConstScalarSubSelect(ifp, funcName)) + { + idbassert(!gwip->ptWorkStack.empty()); + ParseTree* pt = gwip->ptWorkStack.top(); + SimpleFilter* sf = dynamic_cast(pt->data()); + + if (sf) + { + boost::shared_ptr sop(new PredicateOperator("<>")); + sf->op(sop); + return; + } + } + + // Do not call buildSubselectFunc() if the subquery is a const scalar + // subselect of the form: + // (SELECT ) + // As an example: SELECT col1 FROM t1 WHERE col2 = (SELECT 2); + if ((ifp->with_subquery() && !isSecondArgumentConstItem(ifp)) || + funcName == "") { buildSubselectFunc(ifp, gwip); return;