1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-10-31 18:30:33 +03:00

feat(rbo,rules,QA): support expressions in RCs

This commit is contained in:
drrtuy
2025-07-28 12:42:26 +00:00
parent b07ee73fb3
commit 134235b2d2
10 changed files with 120 additions and 75 deletions

View File

@@ -447,24 +447,10 @@ void ArithmeticColumn::setSimpleColumnList()
fExpression->walk(getSimpleCols, &fSimpleColumnList); fExpression->walk(getSimpleCols, &fSimpleColumnList);
} }
bool ArithmeticColumn::singleTable(CalpontSystemCatalog::TableAliasName& tan) std::optional<CalpontSystemCatalog::TableAliasName> ArithmeticColumn::singleTable()
{ {
tan.clear();
setSimpleColumnList(); setSimpleColumnList();
return sameTableCheck(fSimpleColumnList);
for (uint32_t i = 0; i < fSimpleColumnList.size(); i++)
{
CalpontSystemCatalog::TableAliasName stan(
fSimpleColumnList[i]->schemaName(), fSimpleColumnList[i]->tableName(),
fSimpleColumnList[i]->tableAlias(), fSimpleColumnList[i]->viewName());
if (tan.table.empty())
tan = stan;
else if (stan != tan)
return false;
}
return true;
} }
} // namespace execplan } // namespace execplan

View File

@@ -181,7 +181,7 @@ class ArithmeticColumn : public ReturnedColumn
* @return tablename, if all arguments belong to one table * @return tablename, if all arguments belong to one table
* empty string "", if multiple tables are involved in this func * empty string "", if multiple tables are involved in this func
*/ */
bool singleTable(CalpontSystemCatalog::TableAliasName& tan) override; std::optional<CalpontSystemCatalog::TableAliasName> singleTable() override;
std::string toCppCode(IncludeSet& includes) const override; std::string toCppCode(IncludeSet& includes) const override;

View File

@@ -1021,6 +1021,7 @@ execplan::SCSEP CalpontSelectExecutionPlan::cloneForTableWORecursiveSelects(
for (auto* simpleColumn : rc->simpleColumnList()) for (auto* simpleColumn : rc->simpleColumnList())
{ {
// TODO check that is columnstore is correct // TODO check that is columnstore is correct
// use RC::singleTable here
execplan::CalpontSystemCatalog::TableAliasName rcTable( execplan::CalpontSystemCatalog::TableAliasName rcTable(
simpleColumn->schemaName(), simpleColumn->tableName(), simpleColumn->tableAlias(), "", simpleColumn->schemaName(), simpleColumn->tableName(), simpleColumn->tableAlias(), "",
simpleColumn->isColumnStore()); simpleColumn->isColumnStore());

View File

@@ -521,24 +521,10 @@ void FunctionColumn::setSimpleColumnList()
fFunctionParms[i]->walk(getSimpleCols, &fSimpleColumnList); fFunctionParms[i]->walk(getSimpleCols, &fSimpleColumnList);
} }
bool FunctionColumn::singleTable(CalpontSystemCatalog::TableAliasName& tan) std::optional<CalpontSystemCatalog::TableAliasName> FunctionColumn::singleTable()
{ {
tan.clear();
setSimpleColumnList(); setSimpleColumnList();
return sameTableCheck(fSimpleColumnList);
for (uint i = 0; i < fSimpleColumnList.size(); i++)
{
CalpontSystemCatalog::TableAliasName stan(
fSimpleColumnList[i]->schemaName(), fSimpleColumnList[i]->tableName(),
fSimpleColumnList[i]->tableAlias(), fSimpleColumnList[i]->viewName());
if (tan.table.empty())
tan = stan;
else if (stan != tan)
return false;
}
return true;
} }
} // namespace execplan } // namespace execplan

View File

@@ -172,7 +172,7 @@ class FunctionColumn : public ReturnedColumn
* @return true, if all arguments belong to one table * @return true, if all arguments belong to one table
* false, if multiple tables are involved in the function * false, if multiple tables are involved in the function
*/ */
bool singleTable(CalpontSystemCatalog::TableAliasName& tan) override; std::optional<CalpontSystemCatalog::TableAliasName> singleTable() override;
std::string toCppCode(IncludeSet& includes) const override; std::string toCppCode(IncludeSet& includes) const override;

View File

@@ -23,6 +23,7 @@
/** @file */ /** @file */
#pragma once #pragma once
#include <optional>
#include <string> #include <string>
#include <iosfwd> #include <iosfwd>
#include <vector> #include <vector>
@@ -321,9 +322,9 @@ class ReturnedColumn : public TreeNode
* @return true, if all arguments belong to one table * @return true, if all arguments belong to one table
* false, if multiple tables are involved in the function * false, if multiple tables are involved in the function
*/ */
virtual bool singleTable(CalpontSystemCatalog::TableAliasName& /*tan*/) virtual std::optional<CalpontSystemCatalog::TableAliasName> singleTable()
{ {
return false; return std::nullopt;
} }
protected: protected:

View File

@@ -527,13 +527,9 @@ void SimpleColumn::setDerivedTable()
fDerivedTable = ""; fDerivedTable = "";
} }
bool SimpleColumn::singleTable(CalpontSystemCatalog::TableAliasName& tan) std::optional<CalpontSystemCatalog::TableAliasName> SimpleColumn::singleTable()
{ {
tan.table = fTableName; return {CalpontSystemCatalog::TableAliasName(fSchemaName, fTableName, fTableAlias, fViewName)};
tan.schema = fSchemaName;
tan.view = fViewName;
tan.alias = fTableAlias;
return true;
} }
// @todo move to inline // @todo move to inline
@@ -756,4 +752,22 @@ void SimpleColumn::setSimpleColumnList()
fSimpleColumnList.push_back(this); fSimpleColumnList.push_back(this);
} }
std::optional<CalpontSystemCatalog::TableAliasName> sameTableCheck(std::vector<SimpleColumn*> simpleColumnList)
{
std::optional<CalpontSystemCatalog::TableAliasName> tan;
for (SimpleColumn* simpleColumn : simpleColumnList)
{
CalpontSystemCatalog::TableAliasName stan(
simpleColumn->schemaName(), simpleColumn->tableName(),
simpleColumn->tableAlias(), simpleColumn->viewName());
if (!tan.has_value())
tan = stan;
else if (stan != tan)
return std::nullopt;
}
return tan;
}
} // namespace execplan } // namespace execplan

View File

@@ -262,7 +262,7 @@ class SimpleColumn : public ReturnedColumn
* @return true, if all arguments belong to one table * @return true, if all arguments belong to one table
* false, if multiple tables are involved in the function * false, if multiple tables are involved in the function
*/ */
bool singleTable(CalpontSystemCatalog::TableAliasName& tan) override; std::optional<CalpontSystemCatalog::TableAliasName> singleTable() override;
void setSimpleColumnList() override; void setSimpleColumnList() override;
@@ -408,4 +408,6 @@ std::ostream& operator<<(std::ostream& output, const SimpleColumn& rhs);
void getSimpleCols(ParseTree* n, void* obj); void getSimpleCols(ParseTree* n, void* obj);
ParseTree* replaceRefCol(ParseTree*& n, CalpontSelectExecutionPlan::ReturnedColumnList&); ParseTree* replaceRefCol(ParseTree*& n, CalpontSelectExecutionPlan::ReturnedColumnList&);
std::optional<CalpontSystemCatalog::TableAliasName> sameTableCheck(std::vector<SimpleColumn*> simpleColumnList);
} // namespace execplan } // namespace execplan

View File

@@ -1230,19 +1230,20 @@ bool buildEqualityPredicate(execplan::ReturnedColumn* lhs, execplan::ReturnedCol
if (sop->op() == OP_EQ) if (sop->op() == OP_EQ)
{ {
CalpontSystemCatalog::TableAliasName tan_lhs; auto tan_rhs = rhs->singleTable();
CalpontSystemCatalog::TableAliasName tan_rhs; auto tan_lhs = lhs->singleTable();
bool outerjoin = (rhs->singleTable(tan_rhs) && lhs->singleTable(tan_lhs));
bool outerjoin = (tan_rhs && tan_lhs);
// @bug 1632. Alias should be taken account to the identity of tables for selfjoin to work // @bug 1632. Alias should be taken account to the identity of tables for selfjoin to work
if (outerjoin && tan_lhs != tan_rhs) // join if (outerjoin && *tan_lhs != *tan_rhs) // join
{ {
if (!gwip->condPush) // vtable if (!gwip->condPush) // vtable
{ {
if (!gwip->innerTables.empty()) if (!gwip->innerTables.empty())
{ {
checkOuterTableColumn(gwip, tan_lhs, lhs); checkOuterTableColumn(gwip, *tan_lhs, lhs);
checkOuterTableColumn(gwip, tan_rhs, rhs); checkOuterTableColumn(gwip, *tan_rhs, rhs);
} }
if (funcType == Item_func::EQ_FUNC) if (funcType == Item_func::EQ_FUNC)

View File

@@ -238,6 +238,7 @@ execplan::CalpontSelectExecutionPlan::SelectList makeUnionFromTable(
{ {
return unionVec; return unionVec;
} }
auto& bounds = boundsOpt.value(); auto& bounds = boundsOpt.value();
for (auto& bound : bounds) for (auto& bound : bounds)
@@ -254,6 +255,7 @@ bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, RBOptimizerCon
{ {
auto tables = csep.tableList(); auto tables = csep.tableList();
execplan::CalpontSelectExecutionPlan::TableList newTableList; execplan::CalpontSelectExecutionPlan::TableList newTableList;
// TODO support CSEPs with derived tables
execplan::CalpontSelectExecutionPlan::SelectList newDerivedTableList; execplan::CalpontSelectExecutionPlan::SelectList newDerivedTableList;
cal_impl_if::TableAliasMap tableAliasMap; cal_impl_if::TableAliasMap tableAliasMap;
bool ruleHasBeenApplied = false; bool ruleHasBeenApplied = false;
@@ -307,42 +309,94 @@ bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, RBOptimizerCon
} }
} }
// execplan::CalpontSelectExecutionPlan::ReturnedColumnList newReturnedColumns; execplan::CalpontSelectExecutionPlan::ReturnedColumnList newReturnedColumns;
// replace parent CSEP RCs with derived table RCs using ScheamAndTableName -> tableAlias map // replace parent CSEP RCs with derived table RCs using ScheamAndTableName -> tableAlias map
if (!newDerivedTableList.empty()) if (!newDerivedTableList.empty())
{ {
std::cout << "Iterating over RCs" << std::endl;
for (auto& rc : csep.returnedCols()) for (auto& rc : csep.returnedCols())
{ {
auto sameTableAliasOpt = rc->singleTable();
// Same table so RC was pushed into UNION units and can be replaced with new derived table SC
if (sameTableAliasOpt)
{
std::cout << "RC table schema " << sameTableAliasOpt->schema << " table "
<< sameTableAliasOpt->table << " alias " << sameTableAliasOpt->alias << std::endl;
auto tableAliasIt = tableAliasMap.find(*sameTableAliasOpt);
if (tableAliasIt != tableAliasMap.end())
{
// add new SC
auto& [newTableAlias, colPosition] = tableAliasIt->second;
auto newSC = boost::make_shared<execplan::SimpleColumn>(*rc, rc->sessionID());
newSC->tableName("");
newSC->schemaName("");
newSC->tableAlias(newTableAlias);
newSC->colPosition(colPosition++);
newSC->oid(0);
newReturnedColumns.push_back(newSC);
}
// RC doesn't belong to any of the new derived tables
else
{
newReturnedColumns.push_back(rc);
}
}
// if SCs belong to different tables
else
{
rc->setSimpleColumnList();
for (auto* sc : rc->simpleColumnList())
{
// TODO add method to SC to get table alias
// auto scTableAliasOpt = sc->singleTable();
auto tableAliasIt = tableAliasMap.find(*sc->singleTable());
// Need a method to replace original SCs in the SClist
if (tableAliasIt != tableAliasMap.end())
{
auto& [newTableAlias, colPosition] = tableAliasIt->second;
sc->tableName("");
sc->schemaName("");
sc->tableAlias(newTableAlias);
sc->colPosition(colPosition++);
}
// do nothing with this SC
}
newReturnedColumns.push_back(rc);
}
// This part is not used
// TODO support expressions // TODO support expressions
// Find SC for the RC // Find SC for the RC
auto rcCloned = boost::make_shared<execplan::SimpleColumn>(*rc);
// auto rcCloned = boost::make_shared<execplan::SimpleColumn>(*rc, rc->sessionID());
// TODO timezone and result type are not copied // TODO timezone and result type are not copied
// TODO add specific ctor for this functionality // TODO add specific ctor for this functionality
// If there is an alias in the map then it is a new derived table // If there is an alias in the map then it is a new derived table
auto sc = dynamic_cast<execplan::SimpleColumn*>(rc.get());
std::vector<execplan::SimpleColumn*> scs; // auto sc = dynamic_cast<execplan::SimpleColumn*>(rc.get());
// std::vector<execplan::SimpleColumn*> scs;
std::cout << "Processing RC schema " << sc->schemaName() << " table " << sc->tableName() << " alias " // std::cout << "Processing RC schema " << rc->schemaName() << " table " << rc->tableName() << " alias "
<< sc->tableAlias() << std::endl; // << rc->tableAlias() << std::endl;
for (auto& [tableAlias, aliasAndCounter] : tableAliasMap) // for (auto& [tableAlias, aliasAndCounter] : tableAliasMap)
{ // {
std::cout << "Processing table alias " << tableAlias << " new alias " << aliasAndCounter.first // std::cout << "Processing table alias " << tableAlias << " new alias " << aliasAndCounter.first
<< " col position " << aliasAndCounter.second << std::endl; // << " col position " << aliasAndCounter.second << std::endl;
} // }
auto newTableAliasAndColPositionCounter = // auto newTableAliasAndColPositionCounter =
tableAliasMap.find({sc->schemaName(), sc->tableName(), sc->tableAlias(), "", false}); // tableAliasMap.find({sc->schemaName(), sc->tableName(), sc->tableAlias(), "", false});
if (newTableAliasAndColPositionCounter == tableAliasMap.end()) // if (newTableAliasAndColPositionCounter == tableAliasMap.end())
{ // {
std::cout << "The RC doesn't belong to any of the derived tables, so leave it intact" << std::endl; // std::cout << "The RC doesn't belong to any of the derived tables, so leave it intact" << std::endl;
continue; // continue;
} // }
sc->tableName(""); // auto& [newTableAlias, colPosition] = newTableAliasAndColPositionCounter->second;
sc->schemaName("");
auto& [newTableAlias, colPosition] = newTableAliasAndColPositionCounter->second; // sc->tableName("");
sc->tableAlias(newTableAlias); // sc->schemaName("");
// WIP Not needed according with CSEP output // sc->tableAlias(newTableAlias);
// sc->isColumnStore(true); // sc->colPosition(colPosition++);
sc->colPosition(colPosition++);
// rcCloned->isColumnStore(true);
// rcCloned->colPosition(colPosition++); // rcCloned->colPosition(colPosition++);
// rcCloned->resultType(rc->resultType()); // rcCloned->resultType(rc->resultType());
// newReturnedColumns.push_back(rcCloned); // newReturnedColumns.push_back(rcCloned);
@@ -382,7 +436,7 @@ bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, RBOptimizerCon
csep.derivedTableList(newDerivedTableList); csep.derivedTableList(newDerivedTableList);
// Replace table list with new table list populated with union units // Replace table list with new table list populated with union units
csep.tableList(newTableList); csep.tableList(newTableList);
// csep.returnedCols(newReturnedColumns); csep.returnedCols(newReturnedColumns);
} }
return ruleHasBeenApplied; return ruleHasBeenApplied;
} }