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
feat(rbo,rules,QA): support expressions in RCs
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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;
|
|
||||||
|
|
||||||
std::cout << "Processing RC schema " << sc->schemaName() << " table " << sc->tableName() << " alias "
|
// auto sc = dynamic_cast<execplan::SimpleColumn*>(rc.get());
|
||||||
<< sc->tableAlias() << std::endl;
|
// std::vector<execplan::SimpleColumn*> scs;
|
||||||
for (auto& [tableAlias, aliasAndCounter] : tableAliasMap)
|
|
||||||
{
|
// std::cout << "Processing RC schema " << rc->schemaName() << " table " << rc->tableName() << " alias "
|
||||||
std::cout << "Processing table alias " << tableAlias << " new alias " << aliasAndCounter.first
|
// << rc->tableAlias() << std::endl;
|
||||||
<< " col position " << aliasAndCounter.second << std::endl;
|
// for (auto& [tableAlias, aliasAndCounter] : tableAliasMap)
|
||||||
}
|
// {
|
||||||
auto newTableAliasAndColPositionCounter =
|
// std::cout << "Processing table alias " << tableAlias << " new alias " << aliasAndCounter.first
|
||||||
tableAliasMap.find({sc->schemaName(), sc->tableName(), sc->tableAlias(), "", false});
|
// << " col position " << aliasAndCounter.second << std::endl;
|
||||||
if (newTableAliasAndColPositionCounter == tableAliasMap.end())
|
// }
|
||||||
{
|
// auto newTableAliasAndColPositionCounter =
|
||||||
std::cout << "The RC doesn't belong to any of the derived tables, so leave it intact" << std::endl;
|
// tableAliasMap.find({sc->schemaName(), sc->tableName(), sc->tableAlias(), "", false});
|
||||||
continue;
|
// if (newTableAliasAndColPositionCounter == tableAliasMap.end())
|
||||||
}
|
// {
|
||||||
sc->tableName("");
|
// std::cout << "The RC doesn't belong to any of the derived tables, so leave it intact" << std::endl;
|
||||||
sc->schemaName("");
|
// continue;
|
||||||
auto& [newTableAlias, colPosition] = newTableAliasAndColPositionCounter->second;
|
// }
|
||||||
sc->tableAlias(newTableAlias);
|
// auto& [newTableAlias, colPosition] = newTableAliasAndColPositionCounter->second;
|
||||||
// WIP Not needed according with CSEP output
|
|
||||||
// sc->isColumnStore(true);
|
// sc->tableName("");
|
||||||
sc->colPosition(colPosition++);
|
// sc->schemaName("");
|
||||||
|
// sc->tableAlias(newTableAlias);
|
||||||
|
// 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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user