diff --git a/dbcon/execplan/arithmeticcolumn.cpp b/dbcon/execplan/arithmeticcolumn.cpp index 58d11db69..be5a5f5e5 100644 --- a/dbcon/execplan/arithmeticcolumn.cpp +++ b/dbcon/execplan/arithmeticcolumn.cpp @@ -447,24 +447,10 @@ void ArithmeticColumn::setSimpleColumnList() fExpression->walk(getSimpleCols, &fSimpleColumnList); } -bool ArithmeticColumn::singleTable(CalpontSystemCatalog::TableAliasName& tan) +std::optional ArithmeticColumn::singleTable() { - tan.clear(); setSimpleColumnList(); - - 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; + return sameTableCheck(fSimpleColumnList); } } // namespace execplan diff --git a/dbcon/execplan/arithmeticcolumn.h b/dbcon/execplan/arithmeticcolumn.h index 77c7ff927..248962084 100644 --- a/dbcon/execplan/arithmeticcolumn.h +++ b/dbcon/execplan/arithmeticcolumn.h @@ -181,7 +181,7 @@ class ArithmeticColumn : public ReturnedColumn * @return tablename, if all arguments belong to one table * empty string "", if multiple tables are involved in this func */ - bool singleTable(CalpontSystemCatalog::TableAliasName& tan) override; + std::optional singleTable() override; std::string toCppCode(IncludeSet& includes) const override; diff --git a/dbcon/execplan/calpontselectexecutionplan.cpp b/dbcon/execplan/calpontselectexecutionplan.cpp index 723ea9e5c..12774e552 100644 --- a/dbcon/execplan/calpontselectexecutionplan.cpp +++ b/dbcon/execplan/calpontselectexecutionplan.cpp @@ -1021,6 +1021,7 @@ execplan::SCSEP CalpontSelectExecutionPlan::cloneForTableWORecursiveSelects( for (auto* simpleColumn : rc->simpleColumnList()) { // TODO check that is columnstore is correct + // use RC::singleTable here execplan::CalpontSystemCatalog::TableAliasName rcTable( simpleColumn->schemaName(), simpleColumn->tableName(), simpleColumn->tableAlias(), "", simpleColumn->isColumnStore()); diff --git a/dbcon/execplan/functioncolumn.cpp b/dbcon/execplan/functioncolumn.cpp index 720faebe2..0ceb141e4 100644 --- a/dbcon/execplan/functioncolumn.cpp +++ b/dbcon/execplan/functioncolumn.cpp @@ -521,24 +521,10 @@ void FunctionColumn::setSimpleColumnList() fFunctionParms[i]->walk(getSimpleCols, &fSimpleColumnList); } -bool FunctionColumn::singleTable(CalpontSystemCatalog::TableAliasName& tan) +std::optional FunctionColumn::singleTable() { - tan.clear(); setSimpleColumnList(); - - 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; + return sameTableCheck(fSimpleColumnList); } } // namespace execplan diff --git a/dbcon/execplan/functioncolumn.h b/dbcon/execplan/functioncolumn.h index 32ce7fc25..bd209a9bd 100644 --- a/dbcon/execplan/functioncolumn.h +++ b/dbcon/execplan/functioncolumn.h @@ -172,7 +172,7 @@ class FunctionColumn : public ReturnedColumn * @return true, if all arguments belong to one table * false, if multiple tables are involved in the function */ - bool singleTable(CalpontSystemCatalog::TableAliasName& tan) override; + std::optional singleTable() override; std::string toCppCode(IncludeSet& includes) const override; diff --git a/dbcon/execplan/returnedcolumn.h b/dbcon/execplan/returnedcolumn.h index ddf06bec4..25f54a969 100644 --- a/dbcon/execplan/returnedcolumn.h +++ b/dbcon/execplan/returnedcolumn.h @@ -23,6 +23,7 @@ /** @file */ #pragma once +#include #include #include #include @@ -321,9 +322,9 @@ class ReturnedColumn : public TreeNode * @return true, if all arguments belong to one table * false, if multiple tables are involved in the function */ - virtual bool singleTable(CalpontSystemCatalog::TableAliasName& /*tan*/) + virtual std::optional singleTable() { - return false; + return std::nullopt; } protected: diff --git a/dbcon/execplan/simplecolumn.cpp b/dbcon/execplan/simplecolumn.cpp index bb14867c6..800792319 100644 --- a/dbcon/execplan/simplecolumn.cpp +++ b/dbcon/execplan/simplecolumn.cpp @@ -527,13 +527,9 @@ void SimpleColumn::setDerivedTable() fDerivedTable = ""; } -bool SimpleColumn::singleTable(CalpontSystemCatalog::TableAliasName& tan) +std::optional SimpleColumn::singleTable() { - tan.table = fTableName; - tan.schema = fSchemaName; - tan.view = fViewName; - tan.alias = fTableAlias; - return true; + return {CalpontSystemCatalog::TableAliasName(fSchemaName, fTableName, fTableAlias, fViewName)}; } // @todo move to inline @@ -756,4 +752,22 @@ void SimpleColumn::setSimpleColumnList() fSimpleColumnList.push_back(this); } +std::optional sameTableCheck(std::vector simpleColumnList) +{ + std::optional 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 diff --git a/dbcon/execplan/simplecolumn.h b/dbcon/execplan/simplecolumn.h index 8064cdc0f..fb3bc13fe 100644 --- a/dbcon/execplan/simplecolumn.h +++ b/dbcon/execplan/simplecolumn.h @@ -262,7 +262,7 @@ class SimpleColumn : public ReturnedColumn * @return true, if all arguments belong to one table * false, if multiple tables are involved in the function */ - bool singleTable(CalpontSystemCatalog::TableAliasName& tan) override; + std::optional singleTable() override; void setSimpleColumnList() override; @@ -408,4 +408,6 @@ std::ostream& operator<<(std::ostream& output, const SimpleColumn& rhs); void getSimpleCols(ParseTree* n, void* obj); ParseTree* replaceRefCol(ParseTree*& n, CalpontSelectExecutionPlan::ReturnedColumnList&); +std::optional sameTableCheck(std::vector simpleColumnList); + } // namespace execplan diff --git a/dbcon/mysql/ha_mcs_execplan.cpp b/dbcon/mysql/ha_mcs_execplan.cpp index 62b7b1c12..b5dec04b0 100644 --- a/dbcon/mysql/ha_mcs_execplan.cpp +++ b/dbcon/mysql/ha_mcs_execplan.cpp @@ -1230,19 +1230,20 @@ bool buildEqualityPredicate(execplan::ReturnedColumn* lhs, execplan::ReturnedCol if (sop->op() == OP_EQ) { - CalpontSystemCatalog::TableAliasName tan_lhs; - CalpontSystemCatalog::TableAliasName tan_rhs; - bool outerjoin = (rhs->singleTable(tan_rhs) && lhs->singleTable(tan_lhs)); + auto tan_rhs = rhs->singleTable(); + auto tan_lhs = lhs->singleTable(); + + bool outerjoin = (tan_rhs && tan_lhs); // @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->innerTables.empty()) { - checkOuterTableColumn(gwip, tan_lhs, lhs); - checkOuterTableColumn(gwip, tan_rhs, rhs); + checkOuterTableColumn(gwip, *tan_lhs, lhs); + checkOuterTableColumn(gwip, *tan_rhs, rhs); } if (funcType == Item_func::EQ_FUNC) diff --git a/dbcon/mysql/rbo_apply_parallel_ces.cpp b/dbcon/mysql/rbo_apply_parallel_ces.cpp index 782571331..8de9262ca 100644 --- a/dbcon/mysql/rbo_apply_parallel_ces.cpp +++ b/dbcon/mysql/rbo_apply_parallel_ces.cpp @@ -238,6 +238,7 @@ execplan::CalpontSelectExecutionPlan::SelectList makeUnionFromTable( { return unionVec; } + auto& bounds = boundsOpt.value(); for (auto& bound : bounds) @@ -254,6 +255,7 @@ bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, RBOptimizerCon { auto tables = csep.tableList(); execplan::CalpontSelectExecutionPlan::TableList newTableList; + // TODO support CSEPs with derived tables execplan::CalpontSelectExecutionPlan::SelectList newDerivedTableList; cal_impl_if::TableAliasMap tableAliasMap; 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 if (!newDerivedTableList.empty()) { + std::cout << "Iterating over RCs" << std::endl; 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(*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 // Find SC for the RC - auto rcCloned = boost::make_shared(*rc); + + // auto rcCloned = boost::make_shared(*rc, rc->sessionID()); // TODO timezone and result type are not copied // TODO add specific ctor for this functionality // If there is an alias in the map then it is a new derived table - auto sc = dynamic_cast(rc.get()); - std::vector scs; + + // auto sc = dynamic_cast(rc.get()); + // std::vector scs; - std::cout << "Processing RC schema " << sc->schemaName() << " table " << sc->tableName() << " alias " - << sc->tableAlias() << std::endl; - for (auto& [tableAlias, aliasAndCounter] : tableAliasMap) - { - std::cout << "Processing table alias " << tableAlias << " new alias " << aliasAndCounter.first - << " col position " << aliasAndCounter.second << std::endl; - } - auto newTableAliasAndColPositionCounter = - tableAliasMap.find({sc->schemaName(), sc->tableName(), sc->tableAlias(), "", false}); - if (newTableAliasAndColPositionCounter == tableAliasMap.end()) - { - std::cout << "The RC doesn't belong to any of the derived tables, so leave it intact" << std::endl; - continue; - } - sc->tableName(""); - sc->schemaName(""); - auto& [newTableAlias, colPosition] = newTableAliasAndColPositionCounter->second; - sc->tableAlias(newTableAlias); - // WIP Not needed according with CSEP output - // sc->isColumnStore(true); - sc->colPosition(colPosition++); + // std::cout << "Processing RC schema " << rc->schemaName() << " table " << rc->tableName() << " alias " + // << rc->tableAlias() << std::endl; + // for (auto& [tableAlias, aliasAndCounter] : tableAliasMap) + // { + // std::cout << "Processing table alias " << tableAlias << " new alias " << aliasAndCounter.first + // << " col position " << aliasAndCounter.second << std::endl; + // } + // auto newTableAliasAndColPositionCounter = + // tableAliasMap.find({sc->schemaName(), sc->tableName(), sc->tableAlias(), "", false}); + // if (newTableAliasAndColPositionCounter == tableAliasMap.end()) + // { + // std::cout << "The RC doesn't belong to any of the derived tables, so leave it intact" << std::endl; + // continue; + // } + // auto& [newTableAlias, colPosition] = newTableAliasAndColPositionCounter->second; + + // sc->tableName(""); + // sc->schemaName(""); + // sc->tableAlias(newTableAlias); + // sc->colPosition(colPosition++); + + // rcCloned->isColumnStore(true); // rcCloned->colPosition(colPosition++); // rcCloned->resultType(rc->resultType()); // newReturnedColumns.push_back(rcCloned); @@ -382,7 +436,7 @@ bool applyParallelCES(execplan::CalpontSelectExecutionPlan& csep, RBOptimizerCon csep.derivedTableList(newDerivedTableList); // Replace table list with new table list populated with union units csep.tableList(newTableList); - // csep.returnedCols(newReturnedColumns); + csep.returnedCols(newReturnedColumns); } return ruleHasBeenApplied; }