8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/executor/nodeMergejoin.c,v 1.99 2010/01/02 16:57:44 momjian Exp $
11
+ * $PostgreSQL: pgsql/src/backend/executor/nodeMergejoin.c,v 1.100 2010/01/05 23:25:36 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -398,8 +398,13 @@ MJCompare(MergeJoinState *mergestate)
398
398
* want to report that the tuples are equal. Instead, if result is still
399
399
* 0, change it to +1. This will result in advancing the inner side of
400
400
* the join.
401
+ *
402
+ * Likewise, if there was a constant-false joinqual, do not report
403
+ * equality. We have to check this as part of the mergequals, else the
404
+ * rescan logic will do the wrong thing.
401
405
*/
402
- if (nulleqnull && result == 0 )
406
+ if (result == 0 &&
407
+ (nulleqnull || mergestate -> mj_ConstFalseJoin ))
403
408
result = 1 ;
404
409
405
410
MemoryContextSwitchTo (oldContext );
@@ -487,6 +492,32 @@ MJFillInner(MergeJoinState *node)
487
492
}
488
493
489
494
495
+ /*
496
+ * Check that a qual condition is constant true or constant false.
497
+ * If it is constant false (or null), set *is_const_false to TRUE.
498
+ *
499
+ * Constant true would normally be represented by a NIL list, but we allow an
500
+ * actual bool Const as well. We do expect that the planner will have thrown
501
+ * away any non-constant terms that have been ANDed with a constant false.
502
+ */
503
+ static bool
504
+ check_constant_qual (List * qual , bool * is_const_false )
505
+ {
506
+ ListCell * lc ;
507
+
508
+ foreach (lc , qual )
509
+ {
510
+ Const * con = (Const * ) lfirst (lc );
511
+
512
+ if (!con || !IsA (con , Const ))
513
+ return false;
514
+ if (con -> constisnull || !DatumGetBool (con -> constvalue ))
515
+ * is_const_false = true;
516
+ }
517
+ return true;
518
+ }
519
+
520
+
490
521
/* ----------------------------------------------------------------
491
522
* ExecMergeTupleDump
492
523
*
@@ -1025,9 +1056,13 @@ ExecMergeJoin(MergeJoinState *node)
1025
1056
* state for the rescanned inner tuples. We know all of
1026
1057
* them will match this new outer tuple and therefore
1027
1058
* won't be emitted as fill tuples. This works *only*
1028
- * because we require the extra joinquals to be nil when
1029
- * doing a right or full join --- otherwise some of the
1030
- * rescanned tuples might fail the extra joinquals.
1059
+ * because we require the extra joinquals to be constant
1060
+ * when doing a right or full join --- otherwise some of
1061
+ * the rescanned tuples might fail the extra joinquals.
1062
+ * This obviously won't happen for a constant-true extra
1063
+ * joinqual, while the constant-false case is handled by
1064
+ * forcing the merge clause to never match, so we never
1065
+ * get here.
1031
1066
*/
1032
1067
ExecRestrPos (innerPlan );
1033
1068
@@ -1439,6 +1474,7 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
1439
1474
mergestate -> js .joinqual = (List * )
1440
1475
ExecInitExpr ((Expr * ) node -> join .joinqual ,
1441
1476
(PlanState * ) mergestate );
1477
+ mergestate -> mj_ConstFalseJoin = false;
1442
1478
/* mergeclauses are handled below */
1443
1479
1444
1480
/*
@@ -1498,10 +1534,11 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
1498
1534
ExecGetResultType (outerPlanState (mergestate )));
1499
1535
1500
1536
/*
1501
- * Can't handle right or full join with non-nil extra joinclauses.
1502
- * This should have been caught by planner.
1537
+ * Can't handle right or full join with non-constant extra
1538
+ * joinclauses. This should have been caught by planner.
1503
1539
*/
1504
- if (node -> join .joinqual != NIL )
1540
+ if (!check_constant_qual (node -> join .joinqual ,
1541
+ & mergestate -> mj_ConstFalseJoin ))
1505
1542
ereport (ERROR ,
1506
1543
(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
1507
1544
errmsg ("RIGHT JOIN is only supported with merge-joinable join conditions" )));
@@ -1517,9 +1554,11 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
1517
1554
ExecGetResultType (innerPlanState (mergestate )));
1518
1555
1519
1556
/*
1520
- * Can't handle right or full join with non-nil extra joinclauses.
1557
+ * Can't handle right or full join with non-constant extra
1558
+ * joinclauses. This should have been caught by planner.
1521
1559
*/
1522
- if (node -> join .joinqual != NIL )
1560
+ if (!check_constant_qual (node -> join .joinqual ,
1561
+ & mergestate -> mj_ConstFalseJoin ))
1523
1562
ereport (ERROR ,
1524
1563
(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
1525
1564
errmsg ("FULL JOIN is only supported with merge-joinable join conditions" )));
0 commit comments