From fdbf82e48d0b4b9e446fc19ba095c0573e03be7c Mon Sep 17 00:00:00 2001 From: Roman Nozdrin Date: Sun, 29 Apr 2018 21:13:11 +0300 Subject: [PATCH] MCOL-1052 WIP Replace SimpleColumn with ConstantColumn when server pushes equal predicate using cond_push. --- dbcon/mysql/ha_calpont_execplan.cpp | 81 +++++++++++++++++++++++++++-- dbcon/mysql/ha_calpont_impl.cpp | 23 ++++++++ dbcon/mysql/ha_calpont_impl_if.h | 1 + 3 files changed, 100 insertions(+), 5 deletions(-) diff --git a/dbcon/mysql/ha_calpont_execplan.cpp b/dbcon/mysql/ha_calpont_execplan.cpp index 18f5aaaee..f5ba036f1 100644 --- a/dbcon/mysql/ha_calpont_execplan.cpp +++ b/dbcon/mysql/ha_calpont_execplan.cpp @@ -8003,6 +8003,55 @@ int cp_get_group_plan(THD* thd, SCSEP& csep, cal_impl_if::cal_group_info& gi) return 0; } +/*@brief buildConstColFromFilter- change SimpleColumn into ConstColumn*/ +/*********************************************************** + * DESCRIPTION: + * Server could optimize out fields from GROUP BY list, when certain + * filter predicate is used, e.g. + * field = 'AIR', field IN ('AIR'). This utility function tries to + * replace such fields with ConstantColumns using cond_pushed filters. + * PARAMETERS: + * originalSC SimpleColumn* removed field + * gwi main strucutre + * gi auxilary group_by handler structure + * RETURNS + * ConstantColumn* if originalSC equals with cond_pushed columns. + * NULL otherwise + ***********************************************************/ +ConstantColumn* buildConstColFromFilter(SimpleColumn* originalSC, +gp_walk_info& gwi, cal_group_info& gi) +{ + execplan::SimpleColumn* simpleCol; + execplan::ConstantColumn* constCol; + execplan::SOP op; + execplan::SimpleFilter* simpFilter; + execplan::ConstantColumn* result = NULL; + std::vector::iterator ptIt = gi.pushedPts.begin(); + for(; ptIt != gi.pushedPts.end(); ptIt++) + { + simpFilter = dynamic_cast((*ptIt)->data()); + if (simpFilter == NULL) + continue; + simpleCol = dynamic_cast(simpFilter->lhs()); + constCol = dynamic_cast(simpFilter->rhs()); + if(simpleCol == NULL || constCol == NULL) + continue; + op = simpFilter->op(); + if ( originalSC->sameColumn(dynamic_cast(simpleCol)) + && op.get()->op() == OP_EQ && constCol) + { +#ifdef DEBUG_WALK_COND + cerr << "buildConstColFromFilter() replaced " << endl; + cerr << simpleCol->toString() << endl; + cerr << " with " << endl; + cerr << constCol << endl; +#endif + result = constCol; + } + } + return result; +} + int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_group_info& gi, bool isUnion) { #ifdef DEBUG_WALK_COND @@ -8284,7 +8333,9 @@ int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_gro if (filters) { csep->filters(filters); +#ifdef DEBUG_WALK_COND filters->drawTree("/tmp/filter1.dot"); +#endif } gwi.clauseType = SELECT; @@ -8346,6 +8397,7 @@ int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_gro { Item_field* ifp = (Item_field*)item; SimpleColumn* sc = NULL; + ConstantColumn* constCol = NULL; if (ifp->field_name && string(ifp->field_name) == "*") { @@ -8357,6 +8409,8 @@ int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_gro if (sc) { + constCol = buildConstColFromFilter(sc, gwi, gi); + boost::shared_ptr spcc(constCol); boost::shared_ptr spsc(sc); if (sel_cols_in_create.length() != 0) @@ -8386,10 +8440,19 @@ int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_gro escapeBackTick(itemAlias.empty() ? ifp->name : itemAlias.c_str()) + "`"); else gwi.selectCols.push_back("`" + escapeBackTick((itemAlias.empty() ? ifp->name : itemAlias.c_str())) + "`"); - - gwi.returnedCols.push_back(spsc); - - gwi.columnMap.insert(CalpontSelectExecutionPlan::ColumnMap::value_type(string(ifp->field_name), spsc)); + + // MCOL-1052 Replace SimpleColumn with ConstantColumn, + // since it must have a single value only. + if(constCol) + { + gwi.returnedCols.push_back(spcc); + gwi.columnMap.insert(CalpontSelectExecutionPlan::ColumnMap::value_type(string(ifp->field_name), spcc)); + } + else + { + gwi.returnedCols.push_back(spsc); + gwi.columnMap.insert(CalpontSelectExecutionPlan::ColumnMap::value_type(string(ifp->field_name), spsc)); + } TABLE_LIST* tmp = 0; if (ifp->cached_table) @@ -9348,11 +9411,19 @@ int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_gro if( rc->sameColumn((*iter).get()) ) break; } + + // MCOL-1052 Find and remove the optimized field + // from ORDER using cond_pushed filters. + if(buildConstColFromFilter( + dynamic_cast(rc),gwi, gi)) + { + break; + } // MCOL-1052 GROUP BY items list doesn't contain // this ORDER BY item. if ( iter == gwi.groupByCols.end() ) { - Item_ident *iip = reinterpret_cast(ord_item); + Item_ident *iip = reinterpret_cast(ord_item); std::ostringstream ostream; ostream << "'"; if (iip->db_name) diff --git a/dbcon/mysql/ha_calpont_impl.cpp b/dbcon/mysql/ha_calpont_impl.cpp index 27e35e3d1..4fc21b148 100644 --- a/dbcon/mysql/ha_calpont_impl.cpp +++ b/dbcon/mysql/ha_calpont_impl.cpp @@ -5249,6 +5249,29 @@ int ha_calpont_impl_group_by_init(ha_calpont_group_by_handler* group_hand, TABLE gi.groupByHaving = group_hand->having; gi.groupByDistinct = group_hand->distinct; + // MCOL-1052 Send pushed conditions here, since server could omit GROUP BY + // items in case of = or IN functions used on GROUP BY columns. + { + CalTableMap::iterator mapiter; + execplan::CalpontSelectExecutionPlan::ColumnMap::iterator colMapIter; + execplan::CalpontSelectExecutionPlan::ColumnMap::iterator condColMapIter; + execplan::ParseTree* ptIt; + execplan::ReturnedColumn* rcIt; + for(TABLE_LIST* tl = gi.groupByTables; tl; tl=tl->next_local) + { + mapiter = ci->tableMap.find(tl->table); + if(mapiter != ci->tableMap.end() && mapiter->second.condInfo != NULL + && mapiter->second.condInfo->condPush) + { + while(!mapiter->second.condInfo->ptWorkStack.empty()) + { + ptIt=mapiter->second.condInfo->ptWorkStack.top(); + mapiter->second.condInfo->ptWorkStack.pop(); + gi.pushedPts.push_back(ptIt); + } + } + } + } // send plan whenever group_init is called int status = cp_get_group_plan(thd, csep, gi); diff --git a/dbcon/mysql/ha_calpont_impl_if.h b/dbcon/mysql/ha_calpont_impl_if.h index 83f6aaf41..b1e5ec443 100644 --- a/dbcon/mysql/ha_calpont_impl_if.h +++ b/dbcon/mysql/ha_calpont_impl_if.h @@ -211,6 +211,7 @@ struct cal_group_info ORDER* groupByOrder; // MCOL-1052 ORDER BY Item* groupByHaving; // MCOL-1052 HAVING bool groupByDistinct; //MCOL-1052 DISTINCT + std::vector pushedPts; }; typedef std::tr1::unordered_map CalTableMap;