mirror of https://github.com/citusdata/citus.git
find join type from left recursive join tree
parent
8951e99d39
commit
3cc9536bef
|
@ -55,6 +55,7 @@ static RuleEvalFunction RuleEvalFunctionArray[JOIN_RULE_LAST] = { 0 }; /* join r
|
||||||
/* Local functions forward declarations */
|
/* Local functions forward declarations */
|
||||||
static bool JoinExprListWalker(Node *node, List **joinList);
|
static bool JoinExprListWalker(Node *node, List **joinList);
|
||||||
static bool ExtractLeftMostRangeTableIndex(Node *node, int *rangeTableIndex);
|
static bool ExtractLeftMostRangeTableIndex(Node *node, int *rangeTableIndex);
|
||||||
|
static bool ExtractRightMostRangeTableIndex(Node *node, int *rangeTableIndex);
|
||||||
static List * JoinOrderForTable(TableEntry *firstTable, List *tableEntryList,
|
static List * JoinOrderForTable(TableEntry *firstTable, List *tableEntryList,
|
||||||
List *joinClauseList);
|
List *joinClauseList);
|
||||||
static List * BestJoinOrder(List *candidateJoinOrders);
|
static List * BestJoinOrder(List *candidateJoinOrders);
|
||||||
|
@ -64,6 +65,9 @@ static List * LatestLargeDataTransfer(List *candidateJoinOrders);
|
||||||
static void PrintJoinOrderList(List *joinOrder);
|
static void PrintJoinOrderList(List *joinOrder);
|
||||||
static uint32 LargeDataTransferLocation(List *joinOrder);
|
static uint32 LargeDataTransferLocation(List *joinOrder);
|
||||||
static List * TableEntryListDifference(List *lhsTableList, List *rhsTableList);
|
static List * TableEntryListDifference(List *lhsTableList, List *rhsTableList);
|
||||||
|
static bool JoinTypeJoinExprWalker(Node *node, JoinTypeContext *joinTypeContext);
|
||||||
|
static JoinType * FindJoinTypeBetweenTables(List *joinExprList, List *leftTableIdxList,
|
||||||
|
uint32 rtableIdx);
|
||||||
|
|
||||||
/* Local functions forward declarations for join evaluations */
|
/* Local functions forward declarations for join evaluations */
|
||||||
static JoinOrderNode * EvaluateJoinRules(List *joinedTableList,
|
static JoinOrderNode * EvaluateJoinRules(List *joinedTableList,
|
||||||
|
@ -209,6 +213,40 @@ ExtractLeftMostRangeTableIndex(Node *node, int *rangeTableIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ExtractRightMostRangeTableIndex extracts the range table index of the right-most
|
||||||
|
* leaf in a join tree.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
ExtractRightMostRangeTableIndex(Node *node, int *rangeTableIndex)
|
||||||
|
{
|
||||||
|
bool walkerResult = false;
|
||||||
|
|
||||||
|
Assert(node != NULL);
|
||||||
|
|
||||||
|
if (IsA(node, JoinExpr))
|
||||||
|
{
|
||||||
|
JoinExpr *joinExpr = (JoinExpr *) node;
|
||||||
|
|
||||||
|
walkerResult = ExtractRightMostRangeTableIndex(joinExpr->rarg, rangeTableIndex);
|
||||||
|
}
|
||||||
|
else if (IsA(node, RangeTblRef))
|
||||||
|
{
|
||||||
|
RangeTblRef *rangeTableRef = (RangeTblRef *) node;
|
||||||
|
|
||||||
|
*rangeTableIndex = rangeTableRef->rtindex;
|
||||||
|
walkerResult = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
walkerResult = expression_tree_walker(node, ExtractRightMostRangeTableIndex,
|
||||||
|
rangeTableIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return walkerResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* JoinOnColumns determines whether two columns are joined by a given join clause list.
|
* JoinOnColumns determines whether two columns are joined by a given join clause list.
|
||||||
*/
|
*/
|
||||||
|
@ -325,6 +363,71 @@ JoinOrderList(List *tableEntryList, List *joinClauseList)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static JoinType *
|
||||||
|
FindJoinTypeBetweenTables(List *joinExprList, List *leftTableIdxList, uint32 rtableIdx)
|
||||||
|
{
|
||||||
|
uint32 ltableIdx;
|
||||||
|
foreach_int(ltableIdx, leftTableIdxList)
|
||||||
|
{
|
||||||
|
JoinTypeContext joinTypeContext = {
|
||||||
|
.ltableIdx = ltableIdx,
|
||||||
|
.rtableIdx = rtableIdx,
|
||||||
|
.joinType = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
JoinExpr *joinExpr = NULL;
|
||||||
|
foreach_ptr(joinExpr, joinExprList)
|
||||||
|
{
|
||||||
|
JoinTypeJoinExprWalker((Node *) joinExpr, &joinTypeContext);
|
||||||
|
if (joinTypeContext.joinType)
|
||||||
|
{
|
||||||
|
return joinTypeContext.joinType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* JoinTypeJoinExprWalker finds join type between range table indexes.
|
||||||
|
* Only handles left recursive join trees.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
JoinTypeJoinExprWalker(Node *node, JoinTypeContext *joinTypeContext)
|
||||||
|
{
|
||||||
|
if (node == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsA(node, JoinExpr))
|
||||||
|
{
|
||||||
|
JoinExpr *joinExpr = (JoinExpr *) node;
|
||||||
|
|
||||||
|
if (IsA(joinExpr->rarg, RangeTblRef) &&
|
||||||
|
((RangeTblRef *) joinExpr->rarg)->rtindex == joinTypeContext->rtableIdx)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* we found right table entry, then we need to find rightmost entry of left arg
|
||||||
|
* of the join tree
|
||||||
|
*/
|
||||||
|
int ltableIdx = 0;
|
||||||
|
ExtractRightMostRangeTableIndex(joinExpr->larg, <ableIdx);
|
||||||
|
|
||||||
|
if (joinTypeContext->ltableIdx == ltableIdx)
|
||||||
|
{
|
||||||
|
joinTypeContext->joinType = &(joinExpr->jointype);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return expression_tree_walker(node, JoinTypeJoinExprWalker, joinTypeContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FixedJoinOrderList returns the best fixed join order according to
|
* FixedJoinOrderList returns the best fixed join order according to
|
||||||
* applicable join rules for the nodes in the list.
|
* applicable join rules for the nodes in the list.
|
||||||
|
@ -345,13 +448,29 @@ FixedJoinOrderList(List *tableEntryList, List *joinClauseList,
|
||||||
{
|
{
|
||||||
TableEntry *currentTable = (TableEntry *) list_nth(tableEntryList, tableIdx - 1);
|
TableEntry *currentTable = (TableEntry *) list_nth(tableEntryList, tableIdx - 1);
|
||||||
TableEntry *nextTable = (TableEntry *) list_nth(tableEntryList, tableIdx);
|
TableEntry *nextTable = (TableEntry *) list_nth(tableEntryList, tableIdx);
|
||||||
JoinType joinType = ((JoinExpr *) list_nth(joinExprList, tableIdx - 1))->jointype;
|
|
||||||
|
|
||||||
if (firstTable)
|
if (firstTable)
|
||||||
{
|
{
|
||||||
/* add first table into joinedtable list */
|
/* add first table into joinedtable list */
|
||||||
joinedTableList = lappend(joinedTableList, currentTable);
|
joinedTableList = lappend(joinedTableList, currentTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if we cannot find join type between tables, then it is cartesian product. We can use JOIN_INNER,
|
||||||
|
* which will be executed as cartesian product.
|
||||||
|
*/
|
||||||
|
JoinType joinType = JOIN_INNER;
|
||||||
|
List *joinedTableIdxList = RangeTableIdList(joinedTableList);
|
||||||
|
JoinType *applicableJoinType = FindJoinTypeBetweenTables(joinExprList,
|
||||||
|
joinedTableIdxList,
|
||||||
|
nextTable->rangeTableId);
|
||||||
|
if (applicableJoinType)
|
||||||
|
{
|
||||||
|
joinType = *applicableJoinType;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstTable)
|
||||||
|
{
|
||||||
/* create join node for the first table */
|
/* create join node for the first table */
|
||||||
JoinRuleType joinRule = JOIN_RULE_INVALID_FIRST;
|
JoinRuleType joinRule = JOIN_RULE_INVALID_FIRST;
|
||||||
Oid relationId = currentTable->relationId;
|
Oid relationId = currentTable->relationId;
|
||||||
|
|
|
@ -83,6 +83,17 @@ typedef struct JoinOrderNode
|
||||||
} JoinOrderNode;
|
} JoinOrderNode;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* JoinTypeContext stores jointype between given rangetable indexes
|
||||||
|
*/
|
||||||
|
typedef struct JoinTypeContext
|
||||||
|
{
|
||||||
|
uint32 ltableIdx;
|
||||||
|
uint32 rtableIdx;
|
||||||
|
JoinType *joinType;
|
||||||
|
} JoinTypeContext;
|
||||||
|
|
||||||
|
|
||||||
/* Config variables managed via guc.c */
|
/* Config variables managed via guc.c */
|
||||||
extern bool LogMultiJoinOrder;
|
extern bool LogMultiJoinOrder;
|
||||||
extern bool EnableSingleHashRepartitioning;
|
extern bool EnableSingleHashRepartitioning;
|
||||||
|
|
Loading…
Reference in New Issue