1440{
1443 innerDesc;
1445
1446 /* check for unsupported flags */
1448
1450 "initializing node");
1451
1452 /*
1453 * create state structure
1454 */
1461
1462 /*
1463 * Miscellaneous initialization
1464 *
1465 * create expression context for node
1466 */
1468
1469 /*
1470 * we need two additional econtexts in which we can compute the join
1471 * expressions from the left and right input tuples. The node's regular
1472 * econtext won't do because it gets reset too often.
1473 */
1476
1477 /*
1478 * initialize child nodes
1479 *
1480 * inner child must support MARK/RESTORE, unless we have detected that we
1481 * don't need that. Note that skip_mark_restore must never be set if
1482 * there are non-mergeclause joinquals, since the logic wouldn't work.
1483 */
1486
1491 eflags :
1494
1495 /*
1496 * For certain types of inner child nodes, it is advantageous to issue
1497 * MARK every time we advance past an inner tuple we will never return to.
1498 * For other types, MARK on a tuple we cannot return to is a waste of
1499 * cycles. Detect which case applies and set mj_ExtraMarks if we want to
1500 * issue "unnecessary" MARK calls.
1501 *
1502 * Currently, only Material wants the extra MARKs, and it will be helpful
1503 * only if eflags doesn't specify REWIND.
1504 *
1505 * Note that for IndexScan and IndexOnlyScan, it is *necessary* that we
1506 * not set mj_ExtraMarks; otherwise we might attempt to set a mark before
1507 * the first inner tuple, which they do not support.
1508 */
1513 else
1515
1516 /*
1517 * Initialize result slot, type and projection.
1518 */
1521
1522 /*
1523 * tuple table initialization
1524 */
1527 innerOps);
1528
1529 /*
1530 * initialize child expressions
1531 */
1536 /* mergeclauses are handled below */
1537
1538 /*
1539 * detect whether we need only consider the first matching inner tuple
1540 */
1543
1544 /* set up null tuples for outer joins, if needed */
1546 {
1551 break;
1558 break;
1565
1566 /*
1567 * Can't handle right, right-anti or full join with non-constant
1568 * extra joinclauses. This should have been caught by planner.
1569 */
1573 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1574 errmsg(
"RIGHT JOIN is only supported with merge-joinable join conditions")));
1575 break;
1583
1584 /*
1585 * Can't handle right, right-anti or full join with non-constant
1586 * extra joinclauses. This should have been caught by planner.
1587 */
1591 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1592 errmsg(
"FULL JOIN is only supported with merge-joinable join conditions")));
1593 break;
1594 default:
1595 elog(
ERROR,
"unrecognized join type: %d",
1597 }
1598
1599 /*
1600 * preprocess the merge clauses
1601 */
1604 node->mergeFamilies,
1605 node->mergeCollations,
1606 node->mergeReversals,
1607 node->mergeNullsFirst,
1609
1610 /*
1611 * initialize join state
1612 */
1618
1619 /*
1620 * initialization successful
1621 */
1623 "node initialized");
1624
1625 return mergestate;
1626}
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
ExprState * ExecInitQual(List *qual, PlanState *parent)
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
const TupleTableSlotOps TTSOpsVirtual
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)
TupleTableSlot * ExecInitNullTupleSlot(EState *estate, TupleDesc tupType, const TupleTableSlotOps *tts_ops)
TupleDesc ExecGetResultType(PlanState *planstate)
ExprContext * CreateExprContext(EState *estate)
void ExecAssignExprContext(EState *estate, PlanState *planstate)
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
const TupleTableSlotOps * ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
#define EXEC_FLAG_BACKWARD
Assert(PointerIsAligned(start, uint64))
static MergeJoinClause MJExamineQuals(List *mergeclauses, Oid *mergefamilies, Oid *mergecollations, bool *mergereversals, bool *mergenullsfirst, PlanState *parent)
static TupleTableSlot * ExecMergeJoin(PlanState *pstate)
#define EXEC_MJ_INITIALIZE_OUTER
static bool check_constant_qual(List *qual, bool *is_const_false)
#define IsA(nodeptr, _type_)
static int list_length(const List *l)
TupleTableSlot * mj_MarkedTupleSlot
TupleTableSlot * mj_NullInnerTupleSlot
ExprContext * mj_InnerEContext
TupleTableSlot * mj_NullOuterTupleSlot
MergeJoinClause mj_Clauses
TupleTableSlot * mj_InnerTupleSlot
ExprContext * mj_OuterEContext
TupleTableSlot * mj_OuterTupleSlot
ExecProcNodeMtd ExecProcNode