You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-10-31 18:30:33 +03:00
chore(rbo,rules,QA): clone now does not copy OB, GB, HAVING and optionally filters.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -248,41 +248,42 @@ std::optional<FilterRangeBounds<T>> 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::SelectList unionVec;
|
||||
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)
|
||||
{
|
||||
// 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();
|
||||
auto& [keyColumn, columnStatistics] = keyColumnAndStatistics.value();
|
||||
|
||||
std::cout << "makeUnionFromTable keyColumn " << keyColumn.toString() << std::endl;
|
||||
std::cout << "makeUnionFromTable RC front " << csep.returnedCols().front()->toString() << std::endl;
|
||||
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<uint64_t>(columnStatistics);
|
||||
if (!boundsOpt.has_value())
|
||||
{
|
||||
// TODO char and other numerical types support
|
||||
auto boundsOpt = populateRangeBounds<uint64_t>(columnStatistics);
|
||||
if (!boundsOpt.has_value())
|
||||
{
|
||||
return unionVec;
|
||||
}
|
||||
}
|
||||
|
||||
auto& bounds = boundsOpt.value();
|
||||
auto& bounds = boundsOpt.value();
|
||||
|
||||
// These bounds produce low <= col < high
|
||||
if (bounds.size() > 1)
|
||||
{
|
||||
// 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);
|
||||
auto clonedCSEP = csep.cloneForTableWORecursiveSelectsGbObHaving(table);
|
||||
// Add BETWEEN based on key column range
|
||||
auto filter = filtersWithNewRange(clonedCSEP, keyColumn, bounds[i], false);
|
||||
clonedCSEP->filters(filter);
|
||||
@@ -290,27 +291,59 @@ execplan::CalpontSelectExecutionPlan::SelectList makeUnionFromTable(
|
||||
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);
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, RBOptimizerContext& ctx)
|
||||
|
||||
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<execplan::CalpontSelectExecutionPlan*>(derivedSCEP.get());
|
||||
// TODO more rigorous error handling.
|
||||
if (!derivedCSEP)
|
||||
{
|
||||
return execplan::SCSEP();
|
||||
}
|
||||
auto additionalUnionVec = makeUnionFromTable(*derivedCSEP, const_cast<execplan::CalpontSystemCatalog::TableAliasName&>(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<execplan::CalpontSelectExecutionPlan*>(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::string tableAlias = optimizer::RewrittenSubTableAliasPrefix + table.schema + "_" + table.table + "_" +
|
||||
std::to_string(ctx.uniqueId);
|
||||
// TODO add original alias to support multiple same name tables
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user