Test, don't just Assert, that mergejoin's inputs are in order.
authorTom Lane <[email protected]>
Sat, 5 Feb 2022 16:59:30 +0000 (11:59 -0500)
committerTom Lane <[email protected]>
Sat, 5 Feb 2022 16:59:30 +0000 (11:59 -0500)
There are two Asserts in nodeMergejoin.c that are reachable if
the input data is not in the expected order.  This seems way too
fragile.  Alexander Lakhin reported a case where the assertions
could be triggered with misconfigured foreign-table partitions,
and bitter experience with unstable operating system collation
definitions suggests another easy route to hitting them.  Neither
Assert is in a place where we can't afford one more test-and-branch,
so replace 'em with plain test-and-elog logic.

Per bug #17395.  While the reported symptom is relatively recent,
collation changes could happen anytime, so back-patch to all
supported branches.

Discussion: https://postgr.es/m/17395-8c326292078d1a57@postgresql.org

src/backend/executor/nodeMergejoin.c

index eef03825bd92f816b226c4b8af620028449c75b2..10a3a71bd72e9b9bc9bb985bc5a38ced34030fac 100644 (file)
@@ -893,11 +893,10 @@ ExecMergeJoin(PlanState *pstate)
 
                        if (compareResult == 0)
                            node->mj_JoinState = EXEC_MJ_JOINTUPLES;
-                       else
-                       {
-                           Assert(compareResult < 0);
+                       else if (compareResult < 0)
                            node->mj_JoinState = EXEC_MJ_NEXTOUTER;
-                       }
+                       else    /* compareResult > 0 should not happen */
+                           elog(ERROR, "mergejoin input data is out of order");
                        break;
                    case MJEVAL_NONMATCHABLE:
 
@@ -1087,7 +1086,7 @@ ExecMergeJoin(PlanState *pstate)
 
                    node->mj_JoinState = EXEC_MJ_JOINTUPLES;
                }
-               else
+               else if (compareResult > 0)
                {
                    /* ----------------
                     *  if the new outer tuple didn't match the marked inner
@@ -1106,7 +1105,6 @@ ExecMergeJoin(PlanState *pstate)
                     *  no more inners, no more matches are possible.
                     * ----------------
                     */
-                   Assert(compareResult > 0);
                    innerTupleSlot = node->mj_InnerTupleSlot;
 
                    /* reload comparison data for current inner */
@@ -1140,6 +1138,8 @@ ExecMergeJoin(PlanState *pstate)
                            return NULL;
                    }
                }
+               else            /* compareResult < 0 should not happen */
+                   elog(ERROR, "mergejoin input data is out of order");
                break;
 
                /*----------------------------------------------------------