diff options
Diffstat (limited to 'src/backend/executor/nodeMergejoin.c')
-rw-r--r-- | src/backend/executor/nodeMergejoin.c | 59 |
1 files changed, 49 insertions, 10 deletions
diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c index 362181c26f4..0c611015134 100644 --- a/src/backend/executor/nodeMergejoin.c +++ b/src/backend/executor/nodeMergejoin.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/nodeMergejoin.c,v 1.99 2010/01/02 16:57:44 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/executor/nodeMergejoin.c,v 1.100 2010/01/05 23:25:36 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -398,8 +398,13 @@ MJCompare(MergeJoinState *mergestate) * want to report that the tuples are equal. Instead, if result is still * 0, change it to +1. This will result in advancing the inner side of * the join. + * + * Likewise, if there was a constant-false joinqual, do not report + * equality. We have to check this as part of the mergequals, else the + * rescan logic will do the wrong thing. */ - if (nulleqnull && result == 0) + if (result == 0 && + (nulleqnull || mergestate->mj_ConstFalseJoin)) result = 1; MemoryContextSwitchTo(oldContext); @@ -487,6 +492,32 @@ MJFillInner(MergeJoinState *node) } +/* + * Check that a qual condition is constant true or constant false. + * If it is constant false (or null), set *is_const_false to TRUE. + * + * Constant true would normally be represented by a NIL list, but we allow an + * actual bool Const as well. We do expect that the planner will have thrown + * away any non-constant terms that have been ANDed with a constant false. + */ +static bool +check_constant_qual(List *qual, bool *is_const_false) +{ + ListCell *lc; + + foreach(lc, qual) + { + Const *con = (Const *) lfirst(lc); + + if (!con || !IsA(con, Const)) + return false; + if (con->constisnull || !DatumGetBool(con->constvalue)) + *is_const_false = true; + } + return true; +} + + /* ---------------------------------------------------------------- * ExecMergeTupleDump * @@ -1025,9 +1056,13 @@ ExecMergeJoin(MergeJoinState *node) * state for the rescanned inner tuples. We know all of * them will match this new outer tuple and therefore * won't be emitted as fill tuples. This works *only* - * because we require the extra joinquals to be nil when - * doing a right or full join --- otherwise some of the - * rescanned tuples might fail the extra joinquals. + * because we require the extra joinquals to be constant + * when doing a right or full join --- otherwise some of + * the rescanned tuples might fail the extra joinquals. + * This obviously won't happen for a constant-true extra + * joinqual, while the constant-false case is handled by + * forcing the merge clause to never match, so we never + * get here. */ ExecRestrPos(innerPlan); @@ -1439,6 +1474,7 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags) mergestate->js.joinqual = (List *) ExecInitExpr((Expr *) node->join.joinqual, (PlanState *) mergestate); + mergestate->mj_ConstFalseJoin = false; /* mergeclauses are handled below */ /* @@ -1498,10 +1534,11 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags) ExecGetResultType(outerPlanState(mergestate))); /* - * Can't handle right or full join with non-nil extra joinclauses. - * This should have been caught by planner. + * Can't handle right or full join with non-constant extra + * joinclauses. This should have been caught by planner. */ - if (node->join.joinqual != NIL) + if (!check_constant_qual(node->join.joinqual, + &mergestate->mj_ConstFalseJoin)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("RIGHT JOIN is only supported with merge-joinable join conditions"))); @@ -1517,9 +1554,11 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags) ExecGetResultType(innerPlanState(mergestate))); /* - * Can't handle right or full join with non-nil extra joinclauses. + * Can't handle right or full join with non-constant extra + * joinclauses. This should have been caught by planner. */ - if (node->join.joinqual != NIL) + if (!check_constant_qual(node->join.joinqual, + &mergestate->mj_ConstFalseJoin)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("FULL JOIN is only supported with merge-joinable join conditions"))); |