mirror of https://github.com/citusdata/citus.git
Merge pull request #603 from citusdata/fix/outer-join-filter
Do not copy outer join clauses into WHEREpull/608/head
commit
e697bf7ca7
|
@ -59,7 +59,6 @@ static bool HasComplexJoinOrder(Query *queryTree);
|
||||||
static bool HasComplexRangeTableType(Query *queryTree);
|
static bool HasComplexRangeTableType(Query *queryTree);
|
||||||
static void ValidateClauseList(List *clauseList);
|
static void ValidateClauseList(List *clauseList);
|
||||||
static bool ExtractFromExpressionWalker(Node *node, List **qualifierList);
|
static bool ExtractFromExpressionWalker(Node *node, List **qualifierList);
|
||||||
static bool IsJoinClause(Node *clause);
|
|
||||||
static List * MultiTableNodeList(List *tableEntryList, List *rangeTableList);
|
static List * MultiTableNodeList(List *tableEntryList, List *rangeTableList);
|
||||||
static List * AddMultiCollectNodes(List *tableNodeList);
|
static List * AddMultiCollectNodes(List *tableNodeList);
|
||||||
static MultiNode * MultiJoinTree(List *joinOrderList, List *collectTableList,
|
static MultiNode * MultiJoinTree(List *joinOrderList, List *collectTableList,
|
||||||
|
@ -834,8 +833,13 @@ ExtractFromExpressionWalker(Node *node, List **qualifierList)
|
||||||
List *joinQualifierList = NIL;
|
List *joinQualifierList = NIL;
|
||||||
JoinExpr *joinExpression = (JoinExpr *) node;
|
JoinExpr *joinExpression = (JoinExpr *) node;
|
||||||
Node *joinQualifiersNode = joinExpression->quals;
|
Node *joinQualifiersNode = joinExpression->quals;
|
||||||
|
JoinType joinType = joinExpression->jointype;
|
||||||
|
|
||||||
if (joinQualifiersNode != NULL)
|
/*
|
||||||
|
* We only extract qualifiers from inner join clauses, which can be
|
||||||
|
* treated as WHERE clauses.
|
||||||
|
*/
|
||||||
|
if (joinQualifiersNode != NULL && joinType == JOIN_INNER)
|
||||||
{
|
{
|
||||||
if (IsA(joinQualifiersNode, List))
|
if (IsA(joinQualifiersNode, List))
|
||||||
{
|
{
|
||||||
|
@ -888,7 +892,7 @@ ExtractFromExpressionWalker(Node *node, List **qualifierList)
|
||||||
* criteria. Our criteria defines a join clause as an equi join operator between
|
* criteria. Our criteria defines a join clause as an equi join operator between
|
||||||
* two columns that belong to two different tables.
|
* two columns that belong to two different tables.
|
||||||
*/
|
*/
|
||||||
static bool
|
bool
|
||||||
IsJoinClause(Node *clause)
|
IsJoinClause(Node *clause)
|
||||||
{
|
{
|
||||||
bool isJoinClause = false;
|
bool isJoinClause = false;
|
||||||
|
|
|
@ -3286,13 +3286,23 @@ JoinSequenceArray(List *rangeTableFragmentsList, Query *jobQuery, List *depended
|
||||||
foreach(nextJoinClauseCell, nextJoinClauseList)
|
foreach(nextJoinClauseCell, nextJoinClauseList)
|
||||||
{
|
{
|
||||||
OpExpr *nextJoinClause = (OpExpr *) lfirst(nextJoinClauseCell);
|
OpExpr *nextJoinClause = (OpExpr *) lfirst(nextJoinClauseCell);
|
||||||
Var *leftColumn = LeftColumn(nextJoinClause);
|
Var *leftColumn = NULL;
|
||||||
Var *rightColumn = RightColumn(nextJoinClause);
|
Var *rightColumn = NULL;
|
||||||
Index leftRangeTableId = leftColumn->varno;
|
Index leftRangeTableId = 0;
|
||||||
Index rightRangeTableId = rightColumn->varno;
|
Index rightRangeTableId = 0;
|
||||||
bool leftPartitioned = false;
|
bool leftPartitioned = false;
|
||||||
bool rightPartitioned = false;
|
bool rightPartitioned = false;
|
||||||
|
|
||||||
|
if (!IsJoinClause((Node *) nextJoinClause))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
leftColumn = LeftColumn(nextJoinClause);
|
||||||
|
rightColumn = RightColumn(nextJoinClause);
|
||||||
|
leftRangeTableId = leftColumn->varno;
|
||||||
|
rightRangeTableId = rightColumn->varno;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have a table from the existing join list joining with the next
|
* We have a table from the existing join list joining with the next
|
||||||
* table. First resolve the existing table's range table id.
|
* table. First resolve the existing table's range table id.
|
||||||
|
|
|
@ -192,6 +192,7 @@ extern bool BinaryOperator(MultiNode *node);
|
||||||
extern List * OutputTableIdList(MultiNode *multiNode);
|
extern List * OutputTableIdList(MultiNode *multiNode);
|
||||||
extern List * FindNodesOfType(MultiNode *node, int type);
|
extern List * FindNodesOfType(MultiNode *node, int type);
|
||||||
extern List * JoinClauseList(List *whereClauseList);
|
extern List * JoinClauseList(List *whereClauseList);
|
||||||
|
extern bool IsJoinClause(Node *clause);
|
||||||
extern List * SubqueryEntryList(Query *queryTree);
|
extern List * SubqueryEntryList(Query *queryTree);
|
||||||
extern bool ExtractRangeTableIndexWalker(Node *node, List **rangeTableIndexList);
|
extern bool ExtractRangeTableIndexWalker(Node *node, List **rangeTableIndexList);
|
||||||
extern List * WhereClauseList(FromExpr *fromExpr);
|
extern List * WhereClauseList(FromExpr *fromExpr);
|
||||||
|
|
|
@ -113,6 +113,27 @@ WHERE
|
||||||
r_custkey = 5;
|
r_custkey = 5;
|
||||||
|
|
||||||
|
|
||||||
|
-- Apply a filter before the join
|
||||||
|
SELECT
|
||||||
|
count(l_custkey), count(r_custkey)
|
||||||
|
FROM
|
||||||
|
multi_outer_join_left a LEFT JOIN multi_outer_join_right b
|
||||||
|
ON (l_custkey = r_custkey AND r_custkey = 5);
|
||||||
|
|
||||||
|
-- Apply a filter before the join (no matches right)
|
||||||
|
SELECT
|
||||||
|
count(l_custkey), count(r_custkey)
|
||||||
|
FROM
|
||||||
|
multi_outer_join_left a LEFT JOIN multi_outer_join_right b
|
||||||
|
ON (l_custkey = r_custkey AND r_custkey = -1 /* nonexistant */);
|
||||||
|
|
||||||
|
-- Apply a filter before the join (no matches left)
|
||||||
|
SELECT
|
||||||
|
count(l_custkey), count(r_custkey)
|
||||||
|
FROM
|
||||||
|
multi_outer_join_left a LEFT JOIN multi_outer_join_right b
|
||||||
|
ON (l_custkey = r_custkey AND l_custkey = -1 /* nonexistant */);
|
||||||
|
|
||||||
-- Right join should be disallowed in this case
|
-- Right join should be disallowed in this case
|
||||||
SELECT
|
SELECT
|
||||||
min(r_custkey), max(r_custkey)
|
min(r_custkey), max(r_custkey)
|
||||||
|
@ -191,6 +212,14 @@ WHERE
|
||||||
r_custkey = 21;
|
r_custkey = 21;
|
||||||
|
|
||||||
|
|
||||||
|
-- Apply a filter before the join
|
||||||
|
SELECT
|
||||||
|
count(l_custkey), count(r_custkey)
|
||||||
|
FROM
|
||||||
|
multi_outer_join_left a LEFT JOIN multi_outer_join_right b
|
||||||
|
ON (l_custkey = r_custkey AND r_custkey = 21);
|
||||||
|
|
||||||
|
|
||||||
-- Right join should be allowed in this case
|
-- Right join should be allowed in this case
|
||||||
SELECT
|
SELECT
|
||||||
min(r_custkey), max(r_custkey)
|
min(r_custkey), max(r_custkey)
|
||||||
|
|
|
@ -146,6 +146,42 @@ LOG: join order: [ "multi_outer_join_left" ][ broadcast join "multi_outer_join_
|
||||||
5 | 5
|
5 | 5
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
-- Apply a filter before the join
|
||||||
|
SELECT
|
||||||
|
count(l_custkey), count(r_custkey)
|
||||||
|
FROM
|
||||||
|
multi_outer_join_left a LEFT JOIN multi_outer_join_right b
|
||||||
|
ON (l_custkey = r_custkey AND r_custkey = 5);
|
||||||
|
LOG: join order: [ "multi_outer_join_left" ][ broadcast join "multi_outer_join_right" ]
|
||||||
|
count | count
|
||||||
|
-------+-------
|
||||||
|
20 | 1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- Apply a filter before the join (no matches right)
|
||||||
|
SELECT
|
||||||
|
count(l_custkey), count(r_custkey)
|
||||||
|
FROM
|
||||||
|
multi_outer_join_left a LEFT JOIN multi_outer_join_right b
|
||||||
|
ON (l_custkey = r_custkey AND r_custkey = -1 /* nonexistant */);
|
||||||
|
LOG: join order: [ "multi_outer_join_left" ][ broadcast join "multi_outer_join_right" ]
|
||||||
|
count | count
|
||||||
|
-------+-------
|
||||||
|
20 | 0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- Apply a filter before the join (no matches left)
|
||||||
|
SELECT
|
||||||
|
count(l_custkey), count(r_custkey)
|
||||||
|
FROM
|
||||||
|
multi_outer_join_left a LEFT JOIN multi_outer_join_right b
|
||||||
|
ON (l_custkey = r_custkey AND l_custkey = -1 /* nonexistant */);
|
||||||
|
LOG: join order: [ "multi_outer_join_left" ][ broadcast join "multi_outer_join_right" ]
|
||||||
|
count | count
|
||||||
|
-------+-------
|
||||||
|
20 | 0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
-- Right join should be disallowed in this case
|
-- Right join should be disallowed in this case
|
||||||
SELECT
|
SELECT
|
||||||
min(r_custkey), max(r_custkey)
|
min(r_custkey), max(r_custkey)
|
||||||
|
@ -249,6 +285,18 @@ LOG: join order: [ "multi_outer_join_left" ][ local partition join "multi_outer
|
||||||
21 | 21
|
21 | 21
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
-- Apply a filter before the join
|
||||||
|
SELECT
|
||||||
|
count(l_custkey), count(r_custkey)
|
||||||
|
FROM
|
||||||
|
multi_outer_join_left a LEFT JOIN multi_outer_join_right b
|
||||||
|
ON (l_custkey = r_custkey AND r_custkey = 21);
|
||||||
|
LOG: join order: [ "multi_outer_join_left" ][ local partition join "multi_outer_join_right" ]
|
||||||
|
count | count
|
||||||
|
-------+-------
|
||||||
|
25 | 1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
-- Right join should be allowed in this case
|
-- Right join should be allowed in this case
|
||||||
SELECT
|
SELECT
|
||||||
min(r_custkey), max(r_custkey)
|
min(r_custkey), max(r_custkey)
|
||||||
|
|
Loading…
Reference in New Issue