diff --git a/dbcon/execplan/calpontselectexecutionplan.cpp b/dbcon/execplan/calpontselectexecutionplan.cpp index 8b2ea4973..3919b5949 100644 --- a/dbcon/execplan/calpontselectexecutionplan.cpp +++ b/dbcon/execplan/calpontselectexecutionplan.cpp @@ -967,8 +967,9 @@ execplan::SCSEP CalpontSelectExecutionPlan::cloneWORecursiveSelects() return newPlan; } -execplan::SCSEP CalpontSelectExecutionPlan::cloneForTableWORecursiveSelects( - const execplan::CalpontSystemCatalog::TableAliasName& targetTableAlias) +// This clone must return CSEP w/o sub-selects, group by, order by, having limit. +execplan::SCSEP CalpontSelectExecutionPlan::cloneForTableWORecursiveSelectsGbObHaving( + const execplan::CalpontSystemCatalog::TableAliasName& targetTableAlias, const bool withFilters) { execplan::SCSEP newPlan(new CalpontSelectExecutionPlan(fLocation)); @@ -991,9 +992,6 @@ execplan::SCSEP CalpontSelectExecutionPlan::cloneForTableWORecursiveSelects( newPlan->fSubType = fSubType; newPlan->fDerivedTbAlias = fDerivedTbAlias; newPlan->fDerivedTbView = fDerivedTbView; - newPlan->fLimitStart = fLimitStart; - newPlan->fLimitNum = fLimitNum; - newPlan->fHasOrderBy = fHasOrderBy; newPlan->fStringScanThreshold = fStringScanThreshold; newPlan->fQueryType = fQueryType; newPlan->fPriority = fPriority; @@ -1037,34 +1035,13 @@ execplan::SCSEP CalpontSelectExecutionPlan::cloneForTableWORecursiveSelects( // Deep copy of filters // WIP only filters that apply to the target table must be left intact // replace all irrelevant branches with true - if (fFilters) + if (fFilters && withFilters) { newPlan->filters(new ParseTree(*fFilters)); } // Deep copy of filter token list newPlan->filterTokenList(fFilterTokenList); - newPlan->havingTokenList(fHavingTokenList); - - // Deep copy of group by columns - GroupByColumnList newGroupByCols; - for (const auto& col : fGroupByCols) - { - newGroupByCols.push_back(SRCP(col->clone())); - } - newPlan->groupByCols(newGroupByCols); - - // Deep copy of having clause - if (fHaving) - newPlan->having(new ParseTree(*fHaving)); - - // Deep copy of order by columns - OrderByColumnList newOrderByCols; - for (const auto& col : fOrderByCols) - { - newOrderByCols.push_back(SRCP(col->clone())); - } - newPlan->orderByCols(newOrderByCols); // Deep copy of column map ColumnMap newColumnMap; diff --git a/dbcon/execplan/calpontselectexecutionplan.h b/dbcon/execplan/calpontselectexecutionplan.h index e01bab5f2..c9b3c9fea 100644 --- a/dbcon/execplan/calpontselectexecutionplan.h +++ b/dbcon/execplan/calpontselectexecutionplan.h @@ -164,7 +164,8 @@ class CalpontSelectExecutionPlan : public CalpontExecutionPlan */ execplan::SCSEP cloneWORecursiveSelects(); - execplan::SCSEP cloneForTableWORecursiveSelects(const execplan::CalpontSystemCatalog::TableAliasName& targetTableAlias); + execplan::SCSEP cloneForTableWORecursiveSelectsGbObHaving( + const execplan::CalpontSystemCatalog::TableAliasName& targetTableAlias, const bool withFilters = true); /** * Access and mutator methods diff --git a/dbcon/mysql/ha_from_sub.cpp b/dbcon/mysql/ha_from_sub.cpp index 95548e7fa..6a309aff5 100644 --- a/dbcon/mysql/ha_from_sub.cpp +++ b/dbcon/mysql/ha_from_sub.cpp @@ -101,7 +101,6 @@ void derivedTableOptimization(gp_walk_info* gwip, SCSEP& csep) for (int64_t i = cols.size() - 1; i >= 0; i--) { - // if (cols[i]->derivedTable().empty()) if (cols[i]->refCount() == 0) { if (cols[i]->derivedRefCol()) diff --git a/dbcon/mysql/rbo_apply_parallel_ces.cpp b/dbcon/mysql/rbo_apply_parallel_ces.cpp index 039ee9dd1..7b257c78e 100644 --- a/dbcon/mysql/rbo_apply_parallel_ces.cpp +++ b/dbcon/mysql/rbo_apply_parallel_ces.cpp @@ -248,69 +248,102 @@ std::optional> populateRangeBounds(Histogram_json_hb* colum return bounds; } + // TODO char and other numerical types support execplan::CalpontSelectExecutionPlan::SelectList makeUnionFromTable( - execplan::CalpontSelectExecutionPlan& csep, execplan::CalpontSystemCatalog::TableAliasName& table, - optimizer::RBOptimizerContext& ctx) + execplan::CalpontSelectExecutionPlan& csep, execplan::CalpontSystemCatalog::TableAliasName& table, + optimizer::RBOptimizerContext& ctx) { - execplan::CalpontSelectExecutionPlan::SelectList unionVec; - - // SC type controls an integral type used to produce suitable filters. The continuation of this function - // should become a template function based on SC type. - auto keyColumnAndStatistics = chooseKeyColumnAndStatistics(table, ctx); - if (!keyColumnAndStatistics) - { - return unionVec; - } - - auto& [keyColumn, columnStatistics] = keyColumnAndStatistics.value(); - - std::cout << "makeUnionFromTable keyColumn " << keyColumn.toString() << std::endl; - std::cout << "makeUnionFromTable RC front " << csep.returnedCols().front()->toString() << std::endl; - - // TODO char and other numerical types support - auto boundsOpt = populateRangeBounds(columnStatistics); - if (!boundsOpt.has_value()) - { - return unionVec; - } - - auto& bounds = boundsOpt.value(); - - // These bounds produce low <= col < high - if (bounds.size() > 1) - { - for (size_t i = 0; i <= bounds.size() - 2; ++i) - { - auto clonedCSEP = csep.cloneForTableWORecursiveSelects(table); - // Add BETWEEN based on key column range - auto filter = filtersWithNewRange(clonedCSEP, keyColumn, bounds[i], false); - clonedCSEP->filters(filter); - // To create CES filter we need to have a column in the column map - clonedCSEP->columnMap().insert({keyColumn.columnName(), execplan::SRCP(keyColumn.clone())}); - unionVec.push_back(clonedCSEP); - } - } - // This last bound produces low <= col <= high - // TODO add NULLs into filter of the last step - if (!bounds.empty()) - { - auto clonedCSEP = csep.cloneForTableWORecursiveSelects(table); - auto filter = filtersWithNewRange(clonedCSEP, keyColumn, bounds.back(), true); - clonedCSEP->columnMap().insert({keyColumn.columnName(), execplan::SRCP(keyColumn.clone())}); - clonedCSEP->filters(filter); - unionVec.push_back(clonedCSEP); - } +execplan::CalpontSelectExecutionPlan::SelectList unionVec; +// SC type controls an integral type used to produce suitable filters. The continuation of this function +// should become a template function based on SC type. +auto keyColumnAndStatistics = chooseKeyColumnAndStatistics(table, ctx); +if (!keyColumnAndStatistics) +{ return unionVec; } -bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, RBOptimizerContext& ctx) + +auto& [keyColumn, columnStatistics] = keyColumnAndStatistics.value(); + +std::cout << "makeUnionFromTable keyColumn " << keyColumn.toString() << std::endl; +std::cout << "makeUnionFromTable RC front " << csep.returnedCols().front()->toString() << std::endl; + +// TODO char and other numerical types support +auto boundsOpt = populateRangeBounds(columnStatistics); +if (!boundsOpt.has_value()) +{ + return unionVec; +} + +auto& bounds = boundsOpt.value(); + +// These bounds produce low <= col < high +if (bounds.size() > 1) +{ + for (size_t i = 0; i <= bounds.size() - 2; ++i) + { + auto clonedCSEP = csep.cloneForTableWORecursiveSelectsGbObHaving(table); + // Add BETWEEN based on key column range + auto filter = filtersWithNewRange(clonedCSEP, keyColumn, bounds[i], false); + clonedCSEP->filters(filter); + // To create CES filter we need to have a column in the column map + clonedCSEP->columnMap().insert({keyColumn.columnName(), execplan::SRCP(keyColumn.clone())}); + unionVec.push_back(clonedCSEP); + } +} +// This last bound produces low <= col <= high +// TODO add NULLs into filter of the last step +if (!bounds.empty()) +{ + auto clonedCSEP = csep.cloneForTableWORecursiveSelectsGbObHaving(table); + auto filter = filtersWithNewRange(clonedCSEP, keyColumn, bounds.back(), true); + clonedCSEP->columnMap().insert({keyColumn.columnName(), execplan::SRCP(keyColumn.clone())}); + clonedCSEP->filters(filter); + unionVec.push_back(clonedCSEP); +} + +return unionVec; +} + +execplan::SCSEP createDerivedTableFromTable( + execplan::CalpontSelectExecutionPlan& csep, + const execplan::CalpontSystemCatalog::TableAliasName& table, + const std::string& tableAlias, + optimizer::RBOptimizerContext& ctx) +{ + // Don't copy filters for this + auto derivedSCEP = csep.cloneForTableWORecursiveSelectsGbObHaving(table, false); + // Remove the filters as they were pushed down to union units + // This is inappropriate for EXISTS filter and join conditions + // WIP replace with filters applied to filters, so that only relevant filters are left + // WIP Ugly hack to avoid leaks + auto* derivedCSEP = dynamic_cast(derivedSCEP.get()); + // TODO more rigorous error handling. + if (!derivedCSEP) + { + return execplan::SCSEP(); + } + auto additionalUnionVec = makeUnionFromTable(*derivedCSEP, const_cast(table), ctx); + + // TODO add original alias to support multiple same name tables + derivedSCEP->location(execplan::CalpontSelectExecutionPlan::FROM); + derivedSCEP->subType(execplan::CalpontSelectExecutionPlan::FROM_SUBS); + derivedSCEP->derivedTbAlias(tableAlias); + + derivedSCEP->unionVec().insert(derivedSCEP->unionVec().end(), additionalUnionVec.begin(), + additionalUnionVec.end()); + + return derivedSCEP; +} + +bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, optimizer::RBOptimizerContext& ctx) { auto tables = csep.tableList(); execplan::CalpontSelectExecutionPlan::TableList newTableList; // TODO support CSEPs with derived tables execplan::CalpontSelectExecutionPlan::SelectList newDerivedTableList; - cal_impl_if::TableAliasMap tableAliasMap; + optimizer::TableAliasMap tableAliasMap; bool ruleHasBeenApplied = false; for (auto& table : tables) @@ -323,37 +356,14 @@ bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, RBOptimizerCon // TODO add column statistics check to the corresponding match if (!table.isColumnstore() && anyColumnStatistics) { - // Don't copy filters for this - auto derivedSCEP = csep.cloneForTableWORecursiveSelects(table); - // Remove the filters as they were pushed down to union units - // This is inappropriate for EXISTS filter and join conditions - // WIP replace with filters applied to filters, so that only relevant filters are left - // WIP Ugly hack to avoid leaks - auto unusedFilters = derivedSCEP->filters(); - delete unusedFilters; - derivedSCEP->filters(nullptr); - auto* derivedCSEP = dynamic_cast(derivedSCEP.get()); - if (!derivedCSEP) - { - continue; - } - auto additionalUnionVec = makeUnionFromTable(*derivedCSEP, table, ctx); - - // need to add a level here - std::string tableAlias = RewrittenSubTableAliasPrefix + table.schema + "_" + table.table + "_" + - std::to_string(ctx.uniqueId); - // TODO add original alias to support multiple same name tables + std::string tableAlias = optimizer::RewrittenSubTableAliasPrefix + table.schema + "_" + table.table + "_" + + std::to_string(ctx.uniqueId); tableAliasMap.insert({table, {tableAlias, 0}}); - derivedSCEP->location(execplan::CalpontSelectExecutionPlan::FROM); - derivedSCEP->subType(execplan::CalpontSelectExecutionPlan::FROM_SUBS); - derivedSCEP->derivedTbAlias(tableAlias); - - derivedSCEP->unionVec().insert(derivedSCEP->unionVec().end(), additionalUnionVec.begin(), - additionalUnionVec.end()); - - newDerivedTableList.push_back(derivedSCEP); execplan::CalpontSystemCatalog::TableAliasName tn = execplan::make_aliasview("", "", tableAlias, ""); newTableList.push_back(tn); + + auto derivedSCEP = createDerivedTableFromTable(csep, table, tableAlias, ctx); + newDerivedTableList.push_back(std::move(derivedSCEP)); ruleHasBeenApplied = true; } else