aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeMergejoin.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/nodeMergejoin.c')
-rw-r--r--src/backend/executor/nodeMergejoin.c59
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")));