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,69 +248,102 @@ 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& 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<uint64_t>(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<uint64_t>(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<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::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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user