You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-07-30 19:23:07 +03:00
[MCOL-5061] Fix wrong join id
assignment for the views. (#2474)
This patch fixes a wrong `join id` assignment for `TupleHashJoinStep` in a view. After MCOL-334 CS assigns a '-1' as `join id` for `TupleHashJoinStep` in a view, and in this case we cannot apply a filter for specific `Join step`, which is associated with `join id` for 2 reasons: 1. Filters for all `TupleHashJoinSteps` associated with the same `join id`, which is '-1'. 2. When CS creates a `joinIdIndexMap` it eliminates all `join ids` which a less or equal 0. This patch also fixes some tests for the view, which were generated wrong results.
This commit is contained in:
@ -199,6 +199,7 @@ struct JobInfo
|
|||||||
, limitStart(0)
|
, limitStart(0)
|
||||||
, limitCount(-1)
|
, limitCount(-1)
|
||||||
, joinNum(0)
|
, joinNum(0)
|
||||||
|
, joinNumInView(0)
|
||||||
, subLevel(0)
|
, subLevel(0)
|
||||||
, subNum(0)
|
, subNum(0)
|
||||||
, subId(0)
|
, subId(0)
|
||||||
@ -292,6 +293,8 @@ struct JobInfo
|
|||||||
// mixed outer join
|
// mixed outer join
|
||||||
std::map<int, uint64_t> tableSize;
|
std::map<int, uint64_t> tableSize;
|
||||||
int64_t joinNum;
|
int64_t joinNum;
|
||||||
|
// MCOL-5061, MCOL-334.
|
||||||
|
int64_t joinNumInView;
|
||||||
|
|
||||||
// for subquery
|
// for subquery
|
||||||
boost::shared_ptr<int> subCount; // # of subqueries in the query statement
|
boost::shared_ptr<int> subCount; // # of subqueries in the query statement
|
||||||
@ -367,9 +370,9 @@ struct JobInfo
|
|||||||
|
|
||||||
PrimitiveServerThreadPools primitiveServerThreadPools;
|
PrimitiveServerThreadPools primitiveServerThreadPools;
|
||||||
// Represents a `join edges` and `join id` to be restored in `join order` part.
|
// Represents a `join edges` and `join id` to be restored in `join order` part.
|
||||||
std::map<std::pair<uint32_t, uint32_t>, uint32_t> joinEdgesToRestore;
|
std::map<std::pair<uint32_t, uint32_t>, int64_t> joinEdgesToRestore;
|
||||||
// Represents a pair of `table` to be on a large side and weight associated with that table.
|
// Represents a pair of `table` to be on a large side and weight associated with that table.
|
||||||
std::unordered_map<uint32_t, uint32_t> tablesForLargeSide;
|
std::unordered_map<uint32_t, int64_t> tablesForLargeSide;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// defaults okay
|
// defaults okay
|
||||||
|
@ -1166,7 +1166,9 @@ const JobStepVector doJoin(SimpleColumn* sc1, SimpleColumn* sc2, JobInfo& jobInf
|
|||||||
// MCOL-334 joins in views need to have higher priority than SEMI/ANTI
|
// MCOL-334 joins in views need to have higher priority than SEMI/ANTI
|
||||||
if (!view1.empty() && view1 == view2)
|
if (!view1.empty() && view1 == view2)
|
||||||
{
|
{
|
||||||
thj->joinId(-1);
|
// MCOL-5061. We could have a filters to be associated with a specific join id, therefore we cannot have
|
||||||
|
// the same join id for different `TupleHashJoin` steps.
|
||||||
|
thj->joinId(std::numeric_limits<int64_t>::min() + (++jobInfo.joinNumInView));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1621,13 +1621,13 @@ class CircularJoinGraphTransformer
|
|||||||
// For each cycle breaks it and collects join edges.
|
// For each cycle breaks it and collects join edges.
|
||||||
void breakCyclesAndCollectJoinEdges();
|
void breakCyclesAndCollectJoinEdges();
|
||||||
// Removes given `join edge` from the `join graph`.
|
// Removes given `join edge` from the `join graph`.
|
||||||
void breakCycleAndCollectJoinEdge(const std::pair<JoinEdge, uint32_t>& edgeForward);
|
void breakCycleAndCollectJoinEdge(const std::pair<JoinEdge, int64_t>& edgeForward);
|
||||||
// Initializes the `join graph` based on the table connections.
|
// Initializes the `join graph` based on the table connections.
|
||||||
virtual void initializeJoinGraph();
|
virtual void initializeJoinGraph();
|
||||||
// Check if the given join edge has FK - FK relations.
|
// Check if the given join edge has FK - FK relations.
|
||||||
bool isForeignKeyForeignKeyLink(const JoinEdge& edge, statistics::StatisticsManager* statisticsManager);
|
bool isForeignKeyForeignKeyLink(const JoinEdge& edge, statistics::StatisticsManager* statisticsManager);
|
||||||
// Based on column statistics tries to search `join edge` with maximum join cardinality.
|
// Based on column statistics tries to search `join edge` with maximum join cardinality.
|
||||||
virtual void chooseEdgeToTransform(Cycle& cycle, std::pair<JoinEdge, uint32_t>& resultEdge);
|
virtual void chooseEdgeToTransform(Cycle& cycle, std::pair<JoinEdge, int64_t>& resultEdge);
|
||||||
// Removes given `tableId` from adjacent list.
|
// Removes given `tableId` from adjacent list.
|
||||||
void removeFromAdjacentList(uint32_t tableId, std::vector<uint32_t>& adjList);
|
void removeFromAdjacentList(uint32_t tableId, std::vector<uint32_t>& adjList);
|
||||||
// Removes associated join step associated with the given `joinEdge` from job steps.
|
// Removes associated join step associated with the given `joinEdge` from job steps.
|
||||||
@ -1675,7 +1675,7 @@ void CircularJoinGraphTransformer::analyzeJoinGraph(uint32_t currentTable, uint3
|
|||||||
auto nodeIt = currentTable;
|
auto nodeIt = currentTable;
|
||||||
auto nextNode = joinGraph[nodeIt].fParent;
|
auto nextNode = joinGraph[nodeIt].fParent;
|
||||||
// Walk back until we find node `adjNode` we identified before.
|
// Walk back until we find node `adjNode` we identified before.
|
||||||
while (nextNode != UINT_MAX && nextNode != adjNode)
|
while (nextNode != std::numeric_limits<uint32_t>::max() && nextNode != adjNode)
|
||||||
{
|
{
|
||||||
const auto edgeForward = make_pair(nextNode, nodeIt);
|
const auto edgeForward = make_pair(nextNode, nodeIt);
|
||||||
const auto edgeBackward = make_pair(nodeIt, nextNode);
|
const auto edgeBackward = make_pair(nodeIt, nextNode);
|
||||||
@ -1691,7 +1691,7 @@ void CircularJoinGraphTransformer::analyzeJoinGraph(uint32_t currentTable, uint3
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add the last edge.
|
// Add the last edge.
|
||||||
if (nextNode != UINT_MAX)
|
if (nextNode != std::numeric_limits<uint32_t>::max())
|
||||||
{
|
{
|
||||||
const auto edgeForward = make_pair(nextNode, nodeIt);
|
const auto edgeForward = make_pair(nextNode, nodeIt);
|
||||||
const auto edgeBackward = make_pair(nodeIt, nextNode);
|
const auto edgeBackward = make_pair(nodeIt, nextNode);
|
||||||
@ -1813,7 +1813,7 @@ bool CircularJoinGraphTransformer::isForeignKeyForeignKeyLink(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CircularJoinGraphTransformer::chooseEdgeToTransform(Cycle& cycle,
|
void CircularJoinGraphTransformer::chooseEdgeToTransform(Cycle& cycle,
|
||||||
std::pair<JoinEdge, uint32_t>& resultEdge)
|
std::pair<JoinEdge, int64_t>& resultEdge)
|
||||||
{
|
{
|
||||||
// Use statistics if possible.
|
// Use statistics if possible.
|
||||||
auto* statisticsManager = statistics::StatisticsManager::instance();
|
auto* statisticsManager = statistics::StatisticsManager::instance();
|
||||||
@ -1902,7 +1902,7 @@ void CircularJoinGraphTransformer::removeAssociatedHashJoinStepFromJoinSteps(con
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CircularJoinGraphTransformer::breakCycleAndCollectJoinEdge(
|
void CircularJoinGraphTransformer::breakCycleAndCollectJoinEdge(
|
||||||
const std::pair<JoinEdge, uint32_t>& joinEdgeWithWeight)
|
const std::pair<JoinEdge, int64_t>& joinEdgeWithWeight)
|
||||||
{
|
{
|
||||||
// Add edge to be restored.
|
// Add edge to be restored.
|
||||||
jobInfo.joinEdgesToRestore.insert({joinEdgeWithWeight.first, joinEdgeWithWeight.second});
|
jobInfo.joinEdgesToRestore.insert({joinEdgeWithWeight.first, joinEdgeWithWeight.second});
|
||||||
@ -1937,7 +1937,7 @@ void CircularJoinGraphTransformer::breakCyclesAndCollectJoinEdges()
|
|||||||
// For each cycle.
|
// For each cycle.
|
||||||
for (auto& cycle : cycles)
|
for (auto& cycle : cycles)
|
||||||
{
|
{
|
||||||
std::pair<JoinEdge, uint32_t> joinEdgeWithWeight;
|
std::pair<JoinEdge, int64_t> joinEdgeWithWeight;
|
||||||
chooseEdgeToTransform(cycle, joinEdgeWithWeight);
|
chooseEdgeToTransform(cycle, joinEdgeWithWeight);
|
||||||
breakCycleAndCollectJoinEdge(joinEdgeWithWeight);
|
breakCycleAndCollectJoinEdge(joinEdgeWithWeight);
|
||||||
}
|
}
|
||||||
@ -1960,7 +1960,7 @@ void CircularJoinGraphTransformer::initializeJoinGraph()
|
|||||||
void CircularJoinGraphTransformer::transformJoinGraph()
|
void CircularJoinGraphTransformer::transformJoinGraph()
|
||||||
{
|
{
|
||||||
initializeJoinGraph();
|
initializeJoinGraph();
|
||||||
analyzeJoinGraph(/*currentTable=*/headTable, /*prevTable=*/UINT_MAX);
|
analyzeJoinGraph(/*currentTable=*/headTable, /*prevTable=*/std::numeric_limits<uint32_t>::max());
|
||||||
edgesToTransform.clear();
|
edgesToTransform.clear();
|
||||||
breakCyclesAndCollectJoinEdges();
|
breakCyclesAndCollectJoinEdges();
|
||||||
}
|
}
|
||||||
@ -1993,23 +1993,23 @@ class CircularOuterJoinGraphTransformer : public CircularJoinGraphTransformer
|
|||||||
void analyzeJoinGraph(uint32_t currentTable, uint32_t prevTable) override;
|
void analyzeJoinGraph(uint32_t currentTable, uint32_t prevTable) override;
|
||||||
// Chooses a join edge to transform from the given cycle based on the join edge weight,
|
// Chooses a join edge to transform from the given cycle based on the join edge weight,
|
||||||
// the join edge for transformation has a maximum weight in a cycle.
|
// the join edge for transformation has a maximum weight in a cycle.
|
||||||
void chooseEdgeToTransform(Cycle& cycle, std::pair<JoinEdge, uint32_t>& resultEdge) override;
|
void chooseEdgeToTransform(Cycle& cycle, std::pair<JoinEdge, int64_t>& resultEdge) override;
|
||||||
// Returns the min weight among all join weights related to the given `headTable`.
|
// Returns the min weight among all join weights related to the given `headTable`.
|
||||||
uint32_t getSublingsMinWeight(uint32_t headTable, uint32_t associatedTable);
|
int64_t getSublingsMinWeight(uint32_t headTable, uint32_t associatedTable);
|
||||||
// Returns the max weight which is less than given `upperBoundWeight` among all join weights related to
|
// Returns the max weight which is less than given `upperBoundWeight` among all join weights related to
|
||||||
// the given `headTable`.
|
// the given `headTable`.
|
||||||
uint32_t getSublingsMaxWeightLessThan(uint32_t headTable, uint32_t associatedTable,
|
int64_t getSublingsMaxWeightLessThan(uint32_t headTable, uint32_t associatedTable,
|
||||||
uint32_t upperBoundWeight);
|
int64_t upperBoundWeight);
|
||||||
// Initializes `join graph` from the table connections.
|
// Initializes `join graph` from the table connections.
|
||||||
void initializeJoinGraph() override;
|
void initializeJoinGraph() override;
|
||||||
|
|
||||||
// The map which represents a weight for each join edge in join graph.
|
// The map which represents a weight for each join edge in join graph.
|
||||||
std::map<JoinEdge, uint32_t> joinEdgesToWeights;
|
std::map<JoinEdge, int64_t> joinEdgesToWeights;
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t CircularOuterJoinGraphTransformer::getSublingsMinWeight(uint32_t headTable, uint32_t associatedTable)
|
int64_t CircularOuterJoinGraphTransformer::getSublingsMinWeight(uint32_t headTable, uint32_t associatedTable)
|
||||||
{
|
{
|
||||||
uint32_t minWeight = UINT_MAX;
|
int64_t minWeight = std::numeric_limits<int64_t>::max();
|
||||||
for (const auto adjNode : joinGraph[headTable].fAdjacentList)
|
for (const auto adjNode : joinGraph[headTable].fAdjacentList)
|
||||||
{
|
{
|
||||||
if (adjNode != associatedTable)
|
if (adjNode != associatedTable)
|
||||||
@ -2021,11 +2021,11 @@ uint32_t CircularOuterJoinGraphTransformer::getSublingsMinWeight(uint32_t headTa
|
|||||||
return minWeight;
|
return minWeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t CircularOuterJoinGraphTransformer::getSublingsMaxWeightLessThan(uint32_t headTable,
|
int64_t CircularOuterJoinGraphTransformer::getSublingsMaxWeightLessThan(uint32_t headTable,
|
||||||
uint32_t associatedTable,
|
uint32_t associatedTable,
|
||||||
uint32_t upperBoundWeight)
|
int64_t upperBoundWeight)
|
||||||
{
|
{
|
||||||
uint32_t maxWeight = 0;
|
int64_t maxWeight = std::numeric_limits<int64_t>::min();
|
||||||
for (const auto adjNode : joinGraph[headTable].fAdjacentList)
|
for (const auto adjNode : joinGraph[headTable].fAdjacentList)
|
||||||
{
|
{
|
||||||
if (adjNode != associatedTable)
|
if (adjNode != associatedTable)
|
||||||
@ -2048,7 +2048,7 @@ void CircularOuterJoinGraphTransformer::initializeJoinGraph()
|
|||||||
if (jobInfo.trace)
|
if (jobInfo.trace)
|
||||||
std::cout << "Join edges with weights.\n";
|
std::cout << "Join edges with weights.\n";
|
||||||
|
|
||||||
uint32_t minWeightFullGraph = UINT_MAX;
|
int64_t minWeightFullGraph = std::numeric_limits<int64_t>::max();
|
||||||
JoinEdge joinEdgeWithMinWeight(0, 0);
|
JoinEdge joinEdgeWithMinWeight(0, 0);
|
||||||
|
|
||||||
// For each join step we associate a `join id` with `join edge`.
|
// For each join step we associate a `join id` with `join edge`.
|
||||||
@ -2057,7 +2057,7 @@ void CircularOuterJoinGraphTransformer::initializeJoinGraph()
|
|||||||
auto* tupleHashJoinStep = dynamic_cast<TupleHashJoinStep*>(joinStepIt->get());
|
auto* tupleHashJoinStep = dynamic_cast<TupleHashJoinStep*>(joinStepIt->get());
|
||||||
if (tupleHashJoinStep)
|
if (tupleHashJoinStep)
|
||||||
{
|
{
|
||||||
const uint32_t weight = tupleHashJoinStep->joinId();
|
const int64_t weight = tupleHashJoinStep->joinId();
|
||||||
const auto tableKey1 = getTableKey(jobInfo, tupleHashJoinStep->tupleId1());
|
const auto tableKey1 = getTableKey(jobInfo, tupleHashJoinStep->tupleId1());
|
||||||
const auto tableKey2 = getTableKey(jobInfo, tupleHashJoinStep->tupleId2());
|
const auto tableKey2 = getTableKey(jobInfo, tupleHashJoinStep->tupleId2());
|
||||||
|
|
||||||
@ -2110,7 +2110,7 @@ void CircularOuterJoinGraphTransformer::analyzeJoinGraph(uint32_t currentTable,
|
|||||||
joinGraph[currentTable].fTableColor = JoinTableColor::GREY;
|
joinGraph[currentTable].fTableColor = JoinTableColor::GREY;
|
||||||
joinGraph[currentTable].fParent = prevTable;
|
joinGraph[currentTable].fParent = prevTable;
|
||||||
|
|
||||||
std::vector<std::pair<uint32_t, uint32_t>> adjacentListWeighted;
|
std::vector<std::pair<uint32_t, int64_t>> adjacentListWeighted;
|
||||||
// For each adjacent node.
|
// For each adjacent node.
|
||||||
for (const auto adjNode : joinGraph[currentTable].fAdjacentList)
|
for (const auto adjNode : joinGraph[currentTable].fAdjacentList)
|
||||||
{
|
{
|
||||||
@ -2124,7 +2124,7 @@ void CircularOuterJoinGraphTransformer::analyzeJoinGraph(uint32_t currentTable,
|
|||||||
|
|
||||||
// Sort vertices by weights.
|
// Sort vertices by weights.
|
||||||
std::sort(adjacentListWeighted.begin(), adjacentListWeighted.end(),
|
std::sort(adjacentListWeighted.begin(), adjacentListWeighted.end(),
|
||||||
[](const std::pair<uint32_t, uint32_t>& a, const std::pair<uint32_t, uint32_t>& b) {
|
[](const std::pair<uint32_t, int64_t>& a, const std::pair<uint32_t, int64_t>& b) {
|
||||||
return a.second < b.second;
|
return a.second < b.second;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -2148,7 +2148,7 @@ void CircularOuterJoinGraphTransformer::analyzeJoinGraph(uint32_t currentTable,
|
|||||||
auto nodeIt = currentTable;
|
auto nodeIt = currentTable;
|
||||||
auto nextNode = joinGraph[nodeIt].fParent;
|
auto nextNode = joinGraph[nodeIt].fParent;
|
||||||
// Walk back until we find node `adjNode` we identified before.
|
// Walk back until we find node `adjNode` we identified before.
|
||||||
while (nextNode != UINT_MAX && nextNode != adjNode)
|
while (nextNode != std::numeric_limits<uint32_t>::max() && nextNode != adjNode)
|
||||||
{
|
{
|
||||||
const auto edgeForward = make_pair(nextNode, nodeIt);
|
const auto edgeForward = make_pair(nextNode, nodeIt);
|
||||||
const auto edgeBackward = make_pair(nodeIt, nextNode);
|
const auto edgeBackward = make_pair(nodeIt, nextNode);
|
||||||
@ -2164,7 +2164,7 @@ void CircularOuterJoinGraphTransformer::analyzeJoinGraph(uint32_t currentTable,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add the last edge.
|
// Add the last edge.
|
||||||
if (nextNode != UINT_MAX)
|
if (nextNode != std::numeric_limits<uint32_t>::max())
|
||||||
{
|
{
|
||||||
const auto edgeForward = make_pair(nextNode, nodeIt);
|
const auto edgeForward = make_pair(nextNode, nodeIt);
|
||||||
const auto edgeBackward = make_pair(nodeIt, nextNode);
|
const auto edgeBackward = make_pair(nodeIt, nextNode);
|
||||||
@ -2190,9 +2190,9 @@ void CircularOuterJoinGraphTransformer::analyzeJoinGraph(uint32_t currentTable,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CircularOuterJoinGraphTransformer::chooseEdgeToTransform(Cycle& cycle,
|
void CircularOuterJoinGraphTransformer::chooseEdgeToTransform(Cycle& cycle,
|
||||||
std::pair<JoinEdge, uint32_t>& resultEdge)
|
std::pair<JoinEdge, int64_t>& resultEdge)
|
||||||
{
|
{
|
||||||
uint32_t maxWeightInCycle = 0;
|
int64_t maxWeightInCycle = std::numeric_limits<int64_t>::min();
|
||||||
JoinEdge joinEdgeWithMaxWeight;
|
JoinEdge joinEdgeWithMaxWeight;
|
||||||
|
|
||||||
if (jobInfo.trace)
|
if (jobInfo.trace)
|
||||||
@ -2226,6 +2226,10 @@ void CircularOuterJoinGraphTransformer::chooseEdgeToTransform(Cycle& cycle,
|
|||||||
maxWeightInCycle))
|
maxWeightInCycle))
|
||||||
largeSideTable = joinEdgeWithMaxWeight.second;
|
largeSideTable = joinEdgeWithMaxWeight.second;
|
||||||
|
|
||||||
|
if (maxWeightInCycle < 0)
|
||||||
|
maxWeightInCycle = std::numeric_limits<int64_t>::max() + maxWeightInCycle + 1;
|
||||||
|
idbassert(maxWeightInCycle > 0);
|
||||||
|
|
||||||
// Add large table to the map for the `join ordering` part.
|
// Add large table to the map for the `join ordering` part.
|
||||||
if (!jobInfo.tablesForLargeSide.count(largeSideTable))
|
if (!jobInfo.tablesForLargeSide.count(largeSideTable))
|
||||||
jobInfo.tablesForLargeSide.insert({largeSideTable, maxWeightInCycle});
|
jobInfo.tablesForLargeSide.insert({largeSideTable, maxWeightInCycle});
|
||||||
@ -2758,7 +2762,7 @@ bool matchKeys(const vector<uint32_t>& keysToSearch, const vector<uint32_t>& key
|
|||||||
|
|
||||||
void tryToRestoreJoinEdges(JobInfo& jobInfo, JoinInfo* joinInfo, const RowGroup& largeSideRG,
|
void tryToRestoreJoinEdges(JobInfo& jobInfo, JoinInfo* joinInfo, const RowGroup& largeSideRG,
|
||||||
std::vector<uint32_t>& smallKeyIndices, std::vector<uint32_t>& largeKeyIndices,
|
std::vector<uint32_t>& smallKeyIndices, std::vector<uint32_t>& largeKeyIndices,
|
||||||
std::vector<std::string>& traces, std::map<uint32_t, uint32_t>& joinIndexIdMap,
|
std::vector<std::string>& traces, std::map<int64_t, uint32_t>& joinIndexIdMap,
|
||||||
uint32_t smallSideIndex)
|
uint32_t smallSideIndex)
|
||||||
{
|
{
|
||||||
if (!jobInfo.joinEdgesToRestore.size())
|
if (!jobInfo.joinEdgesToRestore.size())
|
||||||
@ -2771,7 +2775,7 @@ void tryToRestoreJoinEdges(JobInfo& jobInfo, JoinInfo* joinInfo, const RowGroup&
|
|||||||
|
|
||||||
std::vector<uint32_t> smallKeyIndicesToRestore;
|
std::vector<uint32_t> smallKeyIndicesToRestore;
|
||||||
std::vector<uint32_t> largeKeyIndicesToRestore;
|
std::vector<uint32_t> largeKeyIndicesToRestore;
|
||||||
std::vector<pair<JoinEdge, uint32_t>> takenEdgesWithJoinIDs;
|
std::vector<pair<JoinEdge, int64_t>> takenEdgesWithJoinIDs;
|
||||||
auto& joinEdgesToRestore = jobInfo.joinEdgesToRestore;
|
auto& joinEdgesToRestore = jobInfo.joinEdgesToRestore;
|
||||||
|
|
||||||
// We could have a multple join edges to restore from the same vertex e.g:
|
// We could have a multple join edges to restore from the same vertex e.g:
|
||||||
@ -2887,7 +2891,7 @@ void tryToRestoreJoinEdges(JobInfo& jobInfo, JoinInfo* joinInfo, const RowGroup&
|
|||||||
}
|
}
|
||||||
|
|
||||||
void matchEdgesInResultRowGroup(const JobInfo& jobInfo, const RowGroup& rg,
|
void matchEdgesInResultRowGroup(const JobInfo& jobInfo, const RowGroup& rg,
|
||||||
std::map<JoinEdge, uint32_t>& edgesToRestore,
|
std::map<JoinEdge, int64_t>& edgesToRestore,
|
||||||
PostJoinFilterKeys& postJoinFilterKeys)
|
PostJoinFilterKeys& postJoinFilterKeys)
|
||||||
{
|
{
|
||||||
if (jobInfo.trace)
|
if (jobInfo.trace)
|
||||||
@ -3069,7 +3073,7 @@ void createPostJoinFilters(const JobInfo& jobInfo, TableInfoMap& tableInfoMap,
|
|||||||
}
|
}
|
||||||
|
|
||||||
SP_JoinInfo joinToLargeTable(uint32_t large, TableInfoMap& tableInfoMap, JobInfo& jobInfo,
|
SP_JoinInfo joinToLargeTable(uint32_t large, TableInfoMap& tableInfoMap, JobInfo& jobInfo,
|
||||||
vector<uint32_t>& joinOrder, std::map<JoinEdge, uint32_t>& joinEdgesToRestore)
|
vector<uint32_t>& joinOrder, std::map<JoinEdge, int64_t>& joinEdgesToRestore)
|
||||||
{
|
{
|
||||||
vector<SP_JoinInfo> smallSides;
|
vector<SP_JoinInfo> smallSides;
|
||||||
tableInfoMap[large].fVisited = true;
|
tableInfoMap[large].fVisited = true;
|
||||||
@ -3578,7 +3582,7 @@ struct JoinOrderData
|
|||||||
{
|
{
|
||||||
uint32_t fTid1;
|
uint32_t fTid1;
|
||||||
uint32_t fTid2;
|
uint32_t fTid2;
|
||||||
uint32_t fJoinId;
|
int64_t fJoinId;
|
||||||
};
|
};
|
||||||
|
|
||||||
void getJoinOrder(vector<JoinOrderData>& joins, JobStepVector& joinSteps, JobInfo& jobInfo)
|
void getJoinOrder(vector<JoinOrderData>& joins, JobStepVector& joinSteps, JobInfo& jobInfo)
|
||||||
@ -3642,7 +3646,7 @@ void joinTablesInOrder(uint32_t largest, JobStepVector& joinSteps, TableInfoMap&
|
|||||||
// 0 - prefer to be on small side, like FROM subquery;
|
// 0 - prefer to be on small side, like FROM subquery;
|
||||||
// 1 - can be on either large or small side;
|
// 1 - can be on either large or small side;
|
||||||
// 2 - must be on large side.
|
// 2 - must be on large side.
|
||||||
map<uint32_t, pair<SJSTEP, int>> joinStepMap;
|
map<uint32_t, pair<SJSTEP, int64_t>> joinStepMap;
|
||||||
BatchPrimitive* bps = NULL;
|
BatchPrimitive* bps = NULL;
|
||||||
SubAdapterStep* tsas = NULL;
|
SubAdapterStep* tsas = NULL;
|
||||||
TupleHashJoinStep* thjs = NULL;
|
TupleHashJoinStep* thjs = NULL;
|
||||||
@ -3715,7 +3719,7 @@ void joinTablesInOrder(uint32_t largest, JobStepVector& joinSteps, TableInfoMap&
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sort the join steps based on join ID.
|
// sort the join steps based on join ID.
|
||||||
vector<JoinOrderData> joins;
|
std::vector<JoinOrderData> joins;
|
||||||
getJoinOrder(joins, joinSteps, jobInfo);
|
getJoinOrder(joins, joinSteps, jobInfo);
|
||||||
|
|
||||||
// join the steps
|
// join the steps
|
||||||
@ -3775,6 +3779,7 @@ void joinTablesInOrder(uint32_t largest, JobStepVector& joinSteps, TableInfoMap&
|
|||||||
// merge in the next step if the large side is the same
|
// merge in the next step if the large side is the same
|
||||||
for (uint64_t ns = js + 1; ns < joins.size(); js++, ns++)
|
for (uint64_t ns = js + 1; ns < joins.size(); js++, ns++)
|
||||||
{
|
{
|
||||||
|
// Check if FE needs table in previous smallsides.
|
||||||
uint32_t tid1 = joins[ns].fTid1;
|
uint32_t tid1 = joins[ns].fTid1;
|
||||||
uint32_t tid2 = joins[ns].fTid2;
|
uint32_t tid2 = joins[ns].fTid2;
|
||||||
uint32_t small = (uint32_t)-1;
|
uint32_t small = (uint32_t)-1;
|
||||||
@ -3901,8 +3906,8 @@ void joinTablesInOrder(uint32_t largest, JobStepVector& joinSteps, TableInfoMap&
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t smallSideIndex = 0;
|
uint32_t smallSideIndex = 0;
|
||||||
std::map<uint32_t, uint32_t> joinIdIndexMap;
|
// Join id to table id.
|
||||||
|
std::map<int64_t, uint32_t> joinIdIndexMap;
|
||||||
for (vector<SP_JoinInfo>::iterator i = smallSides.begin(); i != smallSides.end(); i++, smallSideIndex++)
|
for (vector<SP_JoinInfo>::iterator i = smallSides.begin(); i != smallSides.end(); i++, smallSideIndex++)
|
||||||
{
|
{
|
||||||
JoinInfo* info = i->get();
|
JoinInfo* info = i->get();
|
||||||
@ -4052,7 +4057,7 @@ void joinTablesInOrder(uint32_t largest, JobStepVector& joinSteps, TableInfoMap&
|
|||||||
// The map for in clause filter.
|
// The map for in clause filter.
|
||||||
for (size_t i = 0; i < smallSides.size(); i++)
|
for (size_t i = 0; i < smallSides.size(); i++)
|
||||||
{
|
{
|
||||||
if (smallSides[i]->fJoinData.fJoinId > 0)
|
if (smallSides[i]->fJoinData.fJoinId != 0)
|
||||||
joinIdIndexMap[smallSides[i]->fJoinData.fJoinId] = i;
|
joinIdIndexMap[smallSides[i]->fJoinData.fJoinId] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4119,10 +4124,10 @@ void joinTablesInOrder(uint32_t largest, JobStepVector& joinSteps, TableInfoMap&
|
|||||||
keyToIndexMap.insert(make_pair(rowGroupKeys[i], i));
|
keyToIndexMap.insert(make_pair(rowGroupKeys[i], i));
|
||||||
|
|
||||||
// tables have additional comparisons
|
// tables have additional comparisons
|
||||||
map<uint32_t, int> correlateTables; // index in thjs
|
map<uint32_t, uint32_t> correlateTables; // index in thjs
|
||||||
map<uint32_t, ParseTree*> correlateCompare; // expression
|
map<uint32_t, ParseTree*> correlateCompare; // expression
|
||||||
|
|
||||||
for (size_t i = 0; i != smallSides.size(); i++)
|
for (uint32_t i = 0; i != smallSides.size(); i++)
|
||||||
{
|
{
|
||||||
if ((jointypes[i] & SEMI) || (jointypes[i] & ANTI) || (jointypes[i] & SCALAR))
|
if ((jointypes[i] & SEMI) || (jointypes[i] & ANTI) || (jointypes[i] & SCALAR))
|
||||||
{
|
{
|
||||||
@ -4150,9 +4155,9 @@ void joinTablesInOrder(uint32_t largest, JobStepVector& joinSteps, TableInfoMap&
|
|||||||
}
|
}
|
||||||
|
|
||||||
const vector<uint32_t>& tables = e->tableKeys();
|
const vector<uint32_t>& tables = e->tableKeys();
|
||||||
map<uint32_t, int>::iterator j = correlateTables.end();
|
auto j = correlateTables.end();
|
||||||
|
|
||||||
for (size_t i = 0; i < tables.size(); i++)
|
for (uint32_t i = 0; i < tables.size(); i++)
|
||||||
{
|
{
|
||||||
j = correlateTables.find(tables[i]);
|
j = correlateTables.find(tables[i]);
|
||||||
|
|
||||||
@ -4191,7 +4196,7 @@ void joinTablesInOrder(uint32_t largest, JobStepVector& joinSteps, TableInfoMap&
|
|||||||
eit = readyExpSteps.erase(eit);
|
eit = readyExpSteps.erase(eit);
|
||||||
}
|
}
|
||||||
|
|
||||||
map<uint32_t, int>::iterator k = correlateTables.begin();
|
auto k = correlateTables.begin();
|
||||||
|
|
||||||
while (k != correlateTables.end())
|
while (k != correlateTables.end())
|
||||||
{
|
{
|
||||||
|
@ -63,13 +63,13 @@ select `mcs63_db`.`t1`.`t1_int` AS `t1_int`,`mcs63_db`.`t1`.`t1_char` AS `t1_cha
|
|||||||
SELECT * FROM v4;
|
SELECT * FROM v4;
|
||||||
t1_int t1_char t2_int t2_char
|
t1_int t1_char t2_int t2_char
|
||||||
1 aaa 1 hhh
|
1 aaa 1 hhh
|
||||||
3 ccc 3 iii
|
|
||||||
5 eee 5 jjj
|
|
||||||
7 gggg 7 llll
|
|
||||||
NULL NULL NULL NULL
|
NULL NULL NULL NULL
|
||||||
2 bbb NULL NULL
|
2 bbb NULL NULL
|
||||||
|
3 ccc NULL NULL
|
||||||
4 ddd NULL NULL
|
4 ddd NULL NULL
|
||||||
|
5 eee NULL NULL
|
||||||
6 fff NULL NULL
|
6 fff NULL NULL
|
||||||
|
7 gggg NULL NULL
|
||||||
CREATE VIEW v5 AS SELECT * FROM t1 RIGHT JOIN t2 ON t1.t1_int = t2.t2_int;
|
CREATE VIEW v5 AS SELECT * FROM t1 RIGHT JOIN t2 ON t1.t1_int = t2.t2_int;
|
||||||
SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME='v5' AND TABLE_SCHEMA='mcs63_db';
|
SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME='v5' AND TABLE_SCHEMA='mcs63_db';
|
||||||
VIEW_DEFINITION
|
VIEW_DEFINITION
|
||||||
@ -105,10 +105,10 @@ select `mcs63_db`.`t1`.`t1_int` AS `t1_int`,`mcs63_db`.`t1`.`t1_char` AS `t1_cha
|
|||||||
SELECT * FROM v7;
|
SELECT * FROM v7;
|
||||||
t1_int t1_char t2_int t2_char
|
t1_int t1_char t2_int t2_char
|
||||||
NULL NULL NULL NULL
|
NULL NULL NULL NULL
|
||||||
1 aaa 1 hhh
|
NULL NULL 1 hhh
|
||||||
3 ccc 3 iii
|
NULL NULL 3 iii
|
||||||
5 eee 5 jjj
|
5 eee 5 jjj
|
||||||
7 gggg 7 llll
|
NULL NULL 7 llll
|
||||||
NULL NULL 9 kkkk
|
NULL NULL 9 kkkk
|
||||||
NULL NULL 11 mm
|
NULL NULL 11 mm
|
||||||
NULL NULL 13 n
|
NULL NULL 13 n
|
||||||
|
20
mysql-test/columnstore/bugfixes/mcol-5061.result
Normal file
20
mysql-test/columnstore/bugfixes/mcol-5061.result
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
DROP DATABASE IF EXISTS mcol_5061;
|
||||||
|
CREATE DATABASE mcol_5061;
|
||||||
|
USE mcol_5061;
|
||||||
|
create table t1 (a int, b int) engine=columnstore;
|
||||||
|
create table t2 (a int, b int) engine=columnstore;
|
||||||
|
insert into t1 values (1, 3), (2, 3), (3, 4);
|
||||||
|
insert into t2 values (1, 2), (2, 4), (4, 5);
|
||||||
|
select t1.a as a, t1.b as b, t2.a as c, t2.b as d, t2_1.a as e, t2_1.b as f from t1 left join t2 on (t1.a = t2.a and t2.a > 1) left join t2 as t2_1 on (t1.b = t2_1.b and t2_1.a > 1);
|
||||||
|
a b c d e f
|
||||||
|
1 3 NULL NULL NULL NULL
|
||||||
|
2 3 2 4 NULL NULL
|
||||||
|
3 4 NULL NULL 2 4
|
||||||
|
create or replace view view_test as
|
||||||
|
select t1.a as a, t1.b as b, t2.a as c, t2.b as d, t2_1.a as e, t2_1.b as f from t1 left join t2 on (t1.a = t2.a and t2.a > 1) left join t2 as t2_1 on (t1.b = t2_1.b and t2_1.a > 1);
|
||||||
|
select * from view_test;
|
||||||
|
a b c d e f
|
||||||
|
1 3 NULL NULL NULL NULL
|
||||||
|
2 3 2 4 NULL NULL
|
||||||
|
3 4 NULL NULL 2 4
|
||||||
|
DROP DATABASE mcol_5061;
|
26
mysql-test/columnstore/bugfixes/mcol-5061.test
Normal file
26
mysql-test/columnstore/bugfixes/mcol-5061.test
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#
|
||||||
|
# Test based on Jira MCOL-5061
|
||||||
|
# Reduced customer test case.
|
||||||
|
#
|
||||||
|
|
||||||
|
--source ../include/have_columnstore.inc
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
DROP DATABASE IF EXISTS mcol_5061;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
CREATE DATABASE mcol_5061;
|
||||||
|
USE mcol_5061;
|
||||||
|
|
||||||
|
create table t1 (a int, b int) engine=columnstore;
|
||||||
|
create table t2 (a int, b int) engine=columnstore;
|
||||||
|
|
||||||
|
insert into t1 values (1, 3), (2, 3), (3, 4);
|
||||||
|
insert into t2 values (1, 2), (2, 4), (4, 5);
|
||||||
|
select t1.a as a, t1.b as b, t2.a as c, t2.b as d, t2_1.a as e, t2_1.b as f from t1 left join t2 on (t1.a = t2.a and t2.a > 1) left join t2 as t2_1 on (t1.b = t2_1.b and t2_1.a > 1);
|
||||||
|
|
||||||
|
create or replace view view_test as
|
||||||
|
select t1.a as a, t1.b as b, t2.a as c, t2.b as d, t2_1.a as e, t2_1.b as f from t1 left join t2 on (t1.a = t2.a and t2.a > 1) left join t2 as t2_1 on (t1.b = t2_1.b and t2_1.a > 1);
|
||||||
|
select * from view_test;
|
||||||
|
|
||||||
|
DROP DATABASE mcol_5061;
|
Reference in New Issue
Block a user