mirror of https://github.com/citusdata/citus.git
Make any expression with two or more tables a join expression
parent
4233cd0d9d
commit
61e2501645
|
@ -212,7 +212,6 @@ ExtractLeftMostRangeTableIndex(Node *node, int *rangeTableIndex)
|
||||||
static bool
|
static bool
|
||||||
JoinOnColumns(Var *currentColumn, Var *candidateColumn, List *joinClauseList)
|
JoinOnColumns(Var *currentColumn, Var *candidateColumn, List *joinClauseList)
|
||||||
{
|
{
|
||||||
ListCell *joinClauseCell = NULL;
|
|
||||||
if (currentColumn == NULL || candidateColumn == NULL)
|
if (currentColumn == NULL || candidateColumn == NULL)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -222,15 +221,16 @@ JoinOnColumns(Var *currentColumn, Var *candidateColumn, List *joinClauseList)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(joinClauseCell, joinClauseList)
|
Node *joinClause = NULL;
|
||||||
|
foreach_ptr(joinClause, joinClauseList)
|
||||||
{
|
{
|
||||||
OpExpr *joinClause = castNode(OpExpr, lfirst(joinClauseCell));
|
if (!NodeIsEqualsOpExpr(joinClause))
|
||||||
Var *leftColumn = LeftColumnOrNULL(joinClause);
|
|
||||||
Var *rightColumn = RightColumnOrNULL(joinClause);
|
|
||||||
if (!OperatorImplementsEquality(joinClause->opno))
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
OpExpr *joinClauseOpExpr = castNode(OpExpr, joinClause);
|
||||||
|
Var *leftColumn = LeftColumnOrNULL(joinClauseOpExpr);
|
||||||
|
Var *rightColumn = RightColumnOrNULL(joinClauseOpExpr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if both join columns and both partition key columns match, since the
|
* Check if both join columns and both partition key columns match, since the
|
||||||
|
@ -253,6 +253,22 @@ JoinOnColumns(Var *currentColumn, Var *candidateColumn, List *joinClauseList)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NodeIsEqualsOpExpr checks if the node is an OpExpr, where the operator
|
||||||
|
* matches OperatorImplementsEquality.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
NodeIsEqualsOpExpr(Node *node)
|
||||||
|
{
|
||||||
|
if (!IsA(node, OpExpr))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
OpExpr *opExpr = castNode(OpExpr, node);
|
||||||
|
return OperatorImplementsEquality(opExpr->opno);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* JoinOrderList calculates the best join order and join rules that apply given
|
* JoinOrderList calculates the best join order and join rules that apply given
|
||||||
* the list of tables and join clauses. First, the function generates a set of
|
* the list of tables and join clauses. First, the function generates a set of
|
||||||
|
@ -1010,21 +1026,21 @@ SinglePartitionJoin(JoinOrderNode *currentJoinNode, TableEntry *candidateTable,
|
||||||
OpExpr *
|
OpExpr *
|
||||||
SinglePartitionJoinClause(Var *partitionColumn, List *applicableJoinClauses)
|
SinglePartitionJoinClause(Var *partitionColumn, List *applicableJoinClauses)
|
||||||
{
|
{
|
||||||
ListCell *applicableJoinClauseCell = NULL;
|
|
||||||
if (partitionColumn == NULL)
|
if (partitionColumn == NULL)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(applicableJoinClauseCell, applicableJoinClauses)
|
Node *applicableJoinClause = NULL;
|
||||||
|
foreach_ptr(applicableJoinClause, applicableJoinClauses)
|
||||||
{
|
{
|
||||||
OpExpr *applicableJoinClause = castNode(OpExpr, lfirst(applicableJoinClauseCell));
|
if (!NodeIsEqualsOpExpr(applicableJoinClause))
|
||||||
if (!OperatorImplementsEquality(applicableJoinClause->opno))
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Var *leftColumn = LeftColumnOrNULL(applicableJoinClause);
|
OpExpr *applicableJoinOpExpr = castNode(OpExpr, applicableJoinClause);
|
||||||
Var *rightColumn = RightColumnOrNULL(applicableJoinClause);
|
Var *leftColumn = LeftColumnOrNULL(applicableJoinOpExpr);
|
||||||
|
Var *rightColumn = RightColumnOrNULL(applicableJoinOpExpr);
|
||||||
if (leftColumn == NULL || rightColumn == NULL)
|
if (leftColumn == NULL || rightColumn == NULL)
|
||||||
{
|
{
|
||||||
/* not a simple partition column join */
|
/* not a simple partition column join */
|
||||||
|
@ -1042,7 +1058,7 @@ SinglePartitionJoinClause(Var *partitionColumn, List *applicableJoinClauses)
|
||||||
{
|
{
|
||||||
if (leftColumn->vartype == rightColumn->vartype)
|
if (leftColumn->vartype == rightColumn->vartype)
|
||||||
{
|
{
|
||||||
return applicableJoinClause;
|
return applicableJoinOpExpr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1089,17 +1105,16 @@ DualPartitionJoin(JoinOrderNode *currentJoinNode, TableEntry *candidateTable,
|
||||||
OpExpr *
|
OpExpr *
|
||||||
DualPartitionJoinClause(List *applicableJoinClauses)
|
DualPartitionJoinClause(List *applicableJoinClauses)
|
||||||
{
|
{
|
||||||
ListCell *applicableJoinClauseCell = NULL;
|
Node *applicableJoinClause = NULL;
|
||||||
|
foreach_ptr(applicableJoinClause, applicableJoinClauses)
|
||||||
foreach(applicableJoinClauseCell, applicableJoinClauses)
|
|
||||||
{
|
{
|
||||||
OpExpr *applicableJoinClause = (OpExpr *) lfirst(applicableJoinClauseCell);
|
if (!NodeIsEqualsOpExpr(applicableJoinClause))
|
||||||
if (!OperatorImplementsEquality(applicableJoinClause->opno))
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Var *leftColumn = LeftColumnOrNULL(applicableJoinClause);
|
OpExpr *applicableJoinOpExpr = castNode(OpExpr, applicableJoinClause);
|
||||||
Var *rightColumn = RightColumnOrNULL(applicableJoinClause);
|
Var *leftColumn = LeftColumnOrNULL(applicableJoinOpExpr);
|
||||||
|
Var *rightColumn = RightColumnOrNULL(applicableJoinOpExpr);
|
||||||
|
|
||||||
if (leftColumn == NULL || rightColumn == NULL)
|
if (leftColumn == NULL || rightColumn == NULL)
|
||||||
{
|
{
|
||||||
|
@ -1109,7 +1124,7 @@ DualPartitionJoinClause(List *applicableJoinClauses)
|
||||||
/* we only need to check that the join column types match */
|
/* we only need to check that the join column types match */
|
||||||
if (leftColumn->vartype == rightColumn->vartype)
|
if (leftColumn->vartype == rightColumn->vartype)
|
||||||
{
|
{
|
||||||
return applicableJoinClause;
|
return applicableJoinOpExpr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1170,9 +1185,9 @@ MakeJoinOrderNode(TableEntry *tableEntry, JoinRuleType joinRuleType,
|
||||||
* in either the list of tables on the left *or* in the right hand table.
|
* in either the list of tables on the left *or* in the right hand table.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
IsApplicableJoinClause(List *leftTableIdList, uint32 rightTableId, OpExpr *joinClause)
|
IsApplicableJoinClause(List *leftTableIdList, uint32 rightTableId, Node *joinClause)
|
||||||
{
|
{
|
||||||
List *varList = pull_var_clause_default((Node *) joinClause);
|
List *varList = pull_var_clause_default(joinClause);
|
||||||
Var *var = NULL;
|
Var *var = NULL;
|
||||||
bool joinContainsRightTable = false;
|
bool joinContainsRightTable = false;
|
||||||
foreach_ptr(var, varList)
|
foreach_ptr(var, varList)
|
||||||
|
@ -1208,15 +1223,14 @@ IsApplicableJoinClause(List *leftTableIdList, uint32 rightTableId, OpExpr *joinC
|
||||||
List *
|
List *
|
||||||
ApplicableJoinClauses(List *leftTableIdList, uint32 rightTableId, List *joinClauseList)
|
ApplicableJoinClauses(List *leftTableIdList, uint32 rightTableId, List *joinClauseList)
|
||||||
{
|
{
|
||||||
ListCell *joinClauseCell = NULL;
|
|
||||||
List *applicableJoinClauses = NIL;
|
List *applicableJoinClauses = NIL;
|
||||||
|
|
||||||
/* make sure joinClauseList contains only join clauses */
|
/* make sure joinClauseList contains only join clauses */
|
||||||
joinClauseList = JoinClauseList(joinClauseList);
|
joinClauseList = JoinClauseList(joinClauseList);
|
||||||
|
|
||||||
foreach(joinClauseCell, joinClauseList)
|
Node *joinClause = NULL;
|
||||||
|
foreach_ptr(joinClause, joinClauseList)
|
||||||
{
|
{
|
||||||
OpExpr *joinClause = castNode(OpExpr, lfirst(joinClauseCell));
|
|
||||||
if (IsApplicableJoinClause(leftTableIdList, rightTableId, joinClause))
|
if (IsApplicableJoinClause(leftTableIdList, rightTableId, joinClause))
|
||||||
{
|
{
|
||||||
applicableJoinClauses = lappend(applicableJoinClauses, joinClause);
|
applicableJoinClauses = lappend(applicableJoinClauses, joinClause);
|
||||||
|
|
|
@ -1429,11 +1429,6 @@ IsJoinClause(Node *clause)
|
||||||
{
|
{
|
||||||
Var *var = NULL;
|
Var *var = NULL;
|
||||||
|
|
||||||
if (!IsA(clause, OpExpr))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* take all column references from the clause, if we find 2 column references from a
|
* take all column references from the clause, if we find 2 column references from a
|
||||||
* different relation we assume this is a join clause
|
* different relation we assume this is a join clause
|
||||||
|
@ -1689,7 +1684,7 @@ MultiSelectNode(List *whereClauseList)
|
||||||
foreach(whereClauseCell, whereClauseList)
|
foreach(whereClauseCell, whereClauseList)
|
||||||
{
|
{
|
||||||
Node *whereClause = (Node *) lfirst(whereClauseCell);
|
Node *whereClause = (Node *) lfirst(whereClauseCell);
|
||||||
if (IsSelectClause(whereClause) || or_clause(whereClause))
|
if (IsSelectClause(whereClause))
|
||||||
{
|
{
|
||||||
selectClauseList = lappend(selectClauseList, whereClause);
|
selectClauseList = lappend(selectClauseList, whereClause);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include "distributed/master_protocol.h"
|
#include "distributed/master_protocol.h"
|
||||||
#include "distributed/metadata_cache.h"
|
#include "distributed/metadata_cache.h"
|
||||||
#include "distributed/multi_router_planner.h"
|
#include "distributed/multi_router_planner.h"
|
||||||
|
#include "distributed/multi_join_order.h"
|
||||||
#include "distributed/multi_logical_optimizer.h"
|
#include "distributed/multi_logical_optimizer.h"
|
||||||
#include "distributed/multi_logical_planner.h"
|
#include "distributed/multi_logical_planner.h"
|
||||||
#include "distributed/multi_physical_planner.h"
|
#include "distributed/multi_physical_planner.h"
|
||||||
|
@ -3497,7 +3498,6 @@ JoinSequenceArray(List *rangeTableFragmentsList, Query *jobQuery, List *dependen
|
||||||
JoinExpr *joinExpr = (JoinExpr *) lfirst(joinExprCell);
|
JoinExpr *joinExpr = (JoinExpr *) lfirst(joinExprCell);
|
||||||
RangeTblRef *rightTableRef = (RangeTblRef *) joinExpr->rarg;
|
RangeTblRef *rightTableRef = (RangeTblRef *) joinExpr->rarg;
|
||||||
uint32 nextRangeTableId = rightTableRef->rtindex;
|
uint32 nextRangeTableId = rightTableRef->rtindex;
|
||||||
ListCell *nextJoinClauseCell = NULL;
|
|
||||||
Index existingRangeTableId = 0;
|
Index existingRangeTableId = 0;
|
||||||
bool applyJoinPruning = false;
|
bool applyJoinPruning = false;
|
||||||
|
|
||||||
|
@ -3518,17 +3518,23 @@ JoinSequenceArray(List *rangeTableFragmentsList, Query *jobQuery, List *dependen
|
||||||
* We now determine if we can apply join pruning between existing range
|
* We now determine if we can apply join pruning between existing range
|
||||||
* tables and this new one.
|
* tables and this new one.
|
||||||
*/
|
*/
|
||||||
foreach(nextJoinClauseCell, nextJoinClauseList)
|
Node *nextJoinClause = NULL;
|
||||||
|
foreach_ptr(nextJoinClause, nextJoinClauseList)
|
||||||
{
|
{
|
||||||
OpExpr *nextJoinClause = (OpExpr *) lfirst(nextJoinClauseCell);
|
if (!NodeIsEqualsOpExpr(nextJoinClause))
|
||||||
|
|
||||||
if (!IsJoinClause((Node *) nextJoinClause))
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Var *leftColumn = LeftColumnOrNULL(nextJoinClause);
|
OpExpr *nextJoinClauseOpExpr = castNode(OpExpr, nextJoinClause);
|
||||||
Var *rightColumn = RightColumnOrNULL(nextJoinClause);
|
|
||||||
|
if (!IsJoinClause((Node *) nextJoinClauseOpExpr))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Var *leftColumn = LeftColumnOrNULL(nextJoinClauseOpExpr);
|
||||||
|
Var *rightColumn = RightColumnOrNULL(nextJoinClauseOpExpr);
|
||||||
if (leftColumn == NULL || rightColumn == NULL)
|
if (leftColumn == NULL || rightColumn == NULL)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
@ -3567,7 +3573,7 @@ JoinSequenceArray(List *rangeTableFragmentsList, Query *jobQuery, List *dependen
|
||||||
if (leftPartitioned && rightPartitioned)
|
if (leftPartitioned && rightPartitioned)
|
||||||
{
|
{
|
||||||
/* make sure this join clause references only simple columns */
|
/* make sure this join clause references only simple columns */
|
||||||
CheckJoinBetweenColumns(nextJoinClause);
|
CheckJoinBetweenColumns(nextJoinClauseOpExpr);
|
||||||
|
|
||||||
applyJoinPruning = true;
|
applyJoinPruning = true;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
#ifndef MULTI_JOIN_ORDER_H
|
#ifndef MULTI_JOIN_ORDER_H
|
||||||
#define MULTI_JOIN_ORDER_H
|
#define MULTI_JOIN_ORDER_H
|
||||||
|
|
||||||
|
#include "postgres.h"
|
||||||
|
|
||||||
#include "nodes/pg_list.h"
|
#include "nodes/pg_list.h"
|
||||||
#include "nodes/primnodes.h"
|
#include "nodes/primnodes.h"
|
||||||
|
|
||||||
|
@ -83,9 +85,10 @@ extern bool EnableSingleHashRepartitioning;
|
||||||
extern List * JoinExprList(FromExpr *fromExpr);
|
extern List * JoinExprList(FromExpr *fromExpr);
|
||||||
extern List * JoinOrderList(List *rangeTableEntryList, List *joinClauseList);
|
extern List * JoinOrderList(List *rangeTableEntryList, List *joinClauseList);
|
||||||
extern bool IsApplicableJoinClause(List *leftTableIdList, uint32 rightTableId,
|
extern bool IsApplicableJoinClause(List *leftTableIdList, uint32 rightTableId,
|
||||||
OpExpr *joinClause);
|
Node *joinClause);
|
||||||
extern List * ApplicableJoinClauses(List *leftTableIdList, uint32 rightTableId,
|
extern List * ApplicableJoinClauses(List *leftTableIdList, uint32 rightTableId,
|
||||||
List *joinClauseList);
|
List *joinClauseList);
|
||||||
|
extern bool NodeIsEqualsOpExpr(Node *node);
|
||||||
extern OpExpr * SinglePartitionJoinClause(Var *partitionColumn,
|
extern OpExpr * SinglePartitionJoinClause(Var *partitionColumn,
|
||||||
List *applicableJoinClauses);
|
List *applicableJoinClauses);
|
||||||
extern OpExpr * DualPartitionJoinClause(List *applicableJoinClauses);
|
extern OpExpr * DualPartitionJoinClause(List *applicableJoinClauses);
|
||||||
|
|
Loading…
Reference in New Issue