PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
nodeMergejoin.h File Reference
#include "nodes/execnodes.h"
Include dependency graph for nodeMergejoin.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

MergeJoinStateExecInitMergeJoin (MergeJoin *node, EState *estate, int eflags)
 
void ExecEndMergeJoin (MergeJoinState *node)
 
void ExecReScanMergeJoin (MergeJoinState *node)
 

Function Documentation

◆ ExecEndMergeJoin()

void ExecEndMergeJoin ( MergeJoinState node)

Definition at line 1636 of file nodeMergejoin.c.

1637{
1638 MJ1_printf("ExecEndMergeJoin: %s\n",
1639 "ending node processing");
1640
1641 /*
1642 * shut down the subplans
1643 */
1646
1647 MJ1_printf("ExecEndMergeJoin: %s\n",
1648 "node processing ended");
1649}
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:562
#define MJ1_printf(s, p)
Definition: execdebug.h:121
#define outerPlanState(node)
Definition: execnodes.h:1222
#define innerPlanState(node)
Definition: execnodes.h:1221

References ExecEndNode(), innerPlanState, MJ1_printf, and outerPlanState.

Referenced by ExecEndNode().

◆ ExecInitMergeJoin()

MergeJoinState * ExecInitMergeJoin ( MergeJoin node,
EState estate,
int  eflags 
)

Definition at line 1439 of file nodeMergejoin.c.

1440{
1441 MergeJoinState *mergestate;
1442 TupleDesc outerDesc,
1443 innerDesc;
1444 const TupleTableSlotOps *innerOps;
1445
1446 /* check for unsupported flags */
1447 Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
1448
1449 MJ1_printf("ExecInitMergeJoin: %s\n",
1450 "initializing node");
1451
1452 /*
1453 * create state structure
1454 */
1455 mergestate = makeNode(MergeJoinState);
1456 mergestate->js.ps.plan = (Plan *) node;
1457 mergestate->js.ps.state = estate;
1458 mergestate->js.ps.ExecProcNode = ExecMergeJoin;
1459 mergestate->js.jointype = node->join.jointype;
1460 mergestate->mj_ConstFalseJoin = false;
1461
1462 /*
1463 * Miscellaneous initialization
1464 *
1465 * create expression context for node
1466 */
1467 ExecAssignExprContext(estate, &mergestate->js.ps);
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 */
1474 mergestate->mj_OuterEContext = CreateExprContext(estate);
1475 mergestate->mj_InnerEContext = CreateExprContext(estate);
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 */
1484 Assert(node->join.joinqual == NIL || !node->skip_mark_restore);
1485 mergestate->mj_SkipMarkRestore = node->skip_mark_restore;
1486
1487 outerPlanState(mergestate) = ExecInitNode(outerPlan(node), estate, eflags);
1488 outerDesc = ExecGetResultType(outerPlanState(mergestate));
1489 innerPlanState(mergestate) = ExecInitNode(innerPlan(node), estate,
1490 mergestate->mj_SkipMarkRestore ?
1491 eflags :
1492 (eflags | EXEC_FLAG_MARK));
1493 innerDesc = ExecGetResultType(innerPlanState(mergestate));
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 */
1509 if (IsA(innerPlan(node), Material) &&
1510 (eflags & EXEC_FLAG_REWIND) == 0 &&
1511 !mergestate->mj_SkipMarkRestore)
1512 mergestate->mj_ExtraMarks = true;
1513 else
1514 mergestate->mj_ExtraMarks = false;
1515
1516 /*
1517 * Initialize result slot, type and projection.
1518 */
1520 ExecAssignProjectionInfo(&mergestate->js.ps, NULL);
1521
1522 /*
1523 * tuple table initialization
1524 */
1525 innerOps = ExecGetResultSlotOps(innerPlanState(mergestate), NULL);
1526 mergestate->mj_MarkedTupleSlot = ExecInitExtraTupleSlot(estate, innerDesc,
1527 innerOps);
1528
1529 /*
1530 * initialize child expressions
1531 */
1532 mergestate->js.ps.qual =
1533 ExecInitQual(node->join.plan.qual, (PlanState *) mergestate);
1534 mergestate->js.joinqual =
1535 ExecInitQual(node->join.joinqual, (PlanState *) mergestate);
1536 /* mergeclauses are handled below */
1537
1538 /*
1539 * detect whether we need only consider the first matching inner tuple
1540 */
1541 mergestate->js.single_match = (node->join.inner_unique ||
1542 node->join.jointype == JOIN_SEMI);
1543
1544 /* set up null tuples for outer joins, if needed */
1545 switch (node->join.jointype)
1546 {
1547 case JOIN_INNER:
1548 case JOIN_SEMI:
1549 mergestate->mj_FillOuter = false;
1550 mergestate->mj_FillInner = false;
1551 break;
1552 case JOIN_LEFT:
1553 case JOIN_ANTI:
1554 mergestate->mj_FillOuter = true;
1555 mergestate->mj_FillInner = false;
1556 mergestate->mj_NullInnerTupleSlot =
1557 ExecInitNullTupleSlot(estate, innerDesc, &TTSOpsVirtual);
1558 break;
1559 case JOIN_RIGHT:
1560 case JOIN_RIGHT_ANTI:
1561 mergestate->mj_FillOuter = false;
1562 mergestate->mj_FillInner = true;
1563 mergestate->mj_NullOuterTupleSlot =
1564 ExecInitNullTupleSlot(estate, outerDesc, &TTSOpsVirtual);
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 */
1571 &mergestate->mj_ConstFalseJoin))
1572 ereport(ERROR,
1573 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1574 errmsg("RIGHT JOIN is only supported with merge-joinable join conditions")));
1575 break;
1576 case JOIN_FULL:
1577 mergestate->mj_FillOuter = true;
1578 mergestate->mj_FillInner = true;
1579 mergestate->mj_NullOuterTupleSlot =
1580 ExecInitNullTupleSlot(estate, outerDesc, &TTSOpsVirtual);
1581 mergestate->mj_NullInnerTupleSlot =
1582 ExecInitNullTupleSlot(estate, innerDesc, &TTSOpsVirtual);
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 */
1589 &mergestate->mj_ConstFalseJoin))
1590 ereport(ERROR,
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",
1596 (int) node->join.jointype);
1597 }
1598
1599 /*
1600 * preprocess the merge clauses
1601 */
1602 mergestate->mj_NumClauses = list_length(node->mergeclauses);
1603 mergestate->mj_Clauses = MJExamineQuals(node->mergeclauses,
1604 node->mergeFamilies,
1605 node->mergeCollations,
1606 node->mergeReversals,
1607 node->mergeNullsFirst,
1608 (PlanState *) mergestate);
1609
1610 /*
1611 * initialize join state
1612 */
1614 mergestate->mj_MatchedOuter = false;
1615 mergestate->mj_MatchedInner = false;
1616 mergestate->mj_OuterTupleSlot = NULL;
1617 mergestate->mj_InnerTupleSlot = NULL;
1618
1619 /*
1620 * initialization successful
1621 */
1622 MJ1_printf("ExecInitMergeJoin: %s\n",
1623 "node initialized");
1624
1625 return mergestate;
1626}
#define Assert(condition)
Definition: c.h:812
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define ereport(elevel,...)
Definition: elog.h:149
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:224
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:142
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:84
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:2018
void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1986
TupleTableSlot * ExecInitNullTupleSlot(EState *estate, TupleDesc tupType, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:2034
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:495
ExprContext * CreateExprContext(EState *estate)
Definition: execUtils.c:306
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:485
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition: execUtils.c:583
const TupleTableSlotOps * ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
Definition: execUtils.c:504
#define EXEC_FLAG_BACKWARD
Definition: executor.h:68
#define EXEC_FLAG_REWIND
Definition: executor.h:67
#define EXEC_FLAG_MARK
Definition: executor.h:69
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_)
Definition: nodes.h:158
#define makeNode(_type_)
Definition: nodes.h:155
@ JOIN_SEMI
Definition: nodes.h:307
@ JOIN_FULL
Definition: nodes.h:295
@ JOIN_INNER
Definition: nodes.h:293
@ JOIN_RIGHT
Definition: nodes.h:296
@ JOIN_LEFT
Definition: nodes.h:294
@ JOIN_RIGHT_ANTI
Definition: nodes.h:310
@ JOIN_ANTI
Definition: nodes.h:308
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
#define innerPlan(node)
Definition: plannodes.h:182
#define outerPlan(node)
Definition: plannodes.h:183
JoinType jointype
Definition: execnodes.h:2121
PlanState ps
Definition: execnodes.h:2120
ExprState * joinqual
Definition: execnodes.h:2124
bool single_match
Definition: execnodes.h:2122
List * joinqual
Definition: plannodes.h:794
JoinType jointype
Definition: plannodes.h:792
bool inner_unique
Definition: plannodes.h:793
bool mj_MatchedOuter
Definition: execnodes.h:2179
bool mj_SkipMarkRestore
Definition: execnodes.h:2174
bool mj_ConstFalseJoin
Definition: execnodes.h:2176
TupleTableSlot * mj_MarkedTupleSlot
Definition: execnodes.h:2183
TupleTableSlot * mj_NullInnerTupleSlot
Definition: execnodes.h:2185
ExprContext * mj_InnerEContext
Definition: execnodes.h:2187
TupleTableSlot * mj_NullOuterTupleSlot
Definition: execnodes.h:2184
bool mj_ExtraMarks
Definition: execnodes.h:2175
MergeJoinClause mj_Clauses
Definition: execnodes.h:2172
bool mj_MatchedInner
Definition: execnodes.h:2180
TupleTableSlot * mj_InnerTupleSlot
Definition: execnodes.h:2182
ExprContext * mj_OuterEContext
Definition: execnodes.h:2186
JoinState js
Definition: execnodes.h:2170
TupleTableSlot * mj_OuterTupleSlot
Definition: execnodes.h:2181
List * mergeclauses
Definition: plannodes.h:842
Join join
Definition: plannodes.h:836
bool skip_mark_restore
Definition: plannodes.h:839
ExprState * qual
Definition: execnodes.h:1147
Plan * plan
Definition: execnodes.h:1126
EState * state
Definition: execnodes.h:1128
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:1132

References Assert, check_constant_qual(), CreateExprContext(), elog, ereport, errcode(), errmsg(), ERROR, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, EXEC_FLAG_REWIND, EXEC_MJ_INITIALIZE_OUTER, ExecAssignExprContext(), ExecAssignProjectionInfo(), ExecGetResultSlotOps(), ExecGetResultType(), ExecInitExtraTupleSlot(), ExecInitNode(), ExecInitNullTupleSlot(), ExecInitQual(), ExecInitResultTupleSlotTL(), ExecMergeJoin(), PlanState::ExecProcNode, Join::inner_unique, innerPlan, innerPlanState, IsA, MergeJoin::join, JOIN_ANTI, JOIN_FULL, JOIN_INNER, JOIN_LEFT, JOIN_RIGHT, JOIN_RIGHT_ANTI, JOIN_SEMI, JoinState::joinqual, Join::joinqual, JoinState::jointype, Join::jointype, MergeJoinState::js, list_length(), makeNode, MergeJoin::mergeclauses, MJ1_printf, MergeJoinState::mj_Clauses, MergeJoinState::mj_ConstFalseJoin, MergeJoinState::mj_ExtraMarks, MergeJoinState::mj_FillInner, MergeJoinState::mj_FillOuter, MergeJoinState::mj_InnerEContext, MergeJoinState::mj_InnerTupleSlot, MergeJoinState::mj_JoinState, MergeJoinState::mj_MarkedTupleSlot, MergeJoinState::mj_MatchedInner, MergeJoinState::mj_MatchedOuter, MergeJoinState::mj_NullInnerTupleSlot, MergeJoinState::mj_NullOuterTupleSlot, MergeJoinState::mj_NumClauses, MergeJoinState::mj_OuterEContext, MergeJoinState::mj_OuterTupleSlot, MergeJoinState::mj_SkipMarkRestore, MJExamineQuals(), NIL, outerPlan, outerPlanState, PlanState::plan, JoinState::ps, PlanState::qual, JoinState::single_match, MergeJoin::skip_mark_restore, PlanState::state, and TTSOpsVirtual.

Referenced by ExecInitNode().

◆ ExecReScanMergeJoin()

void ExecReScanMergeJoin ( MergeJoinState node)

Definition at line 1652 of file nodeMergejoin.c.

1653{
1656
1658
1660 node->mj_MatchedOuter = false;
1661 node->mj_MatchedInner = false;
1662 node->mj_OuterTupleSlot = NULL;
1663 node->mj_InnerTupleSlot = NULL;
1664
1665 /*
1666 * if chgParam of subnodes is not null then plans will be re-scanned by
1667 * first ExecProcNode.
1668 */
1669 if (outerPlan->chgParam == NULL)
1671 if (innerPlan->chgParam == NULL)
1673}
void ExecReScan(PlanState *node)
Definition: execAmi.c:76
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:454

References EXEC_MJ_INITIALIZE_OUTER, ExecClearTuple(), ExecReScan(), innerPlan, innerPlanState, MergeJoinState::mj_InnerTupleSlot, MergeJoinState::mj_JoinState, MergeJoinState::mj_MarkedTupleSlot, MergeJoinState::mj_MatchedInner, MergeJoinState::mj_MatchedOuter, MergeJoinState::mj_OuterTupleSlot, outerPlan, and outerPlanState.

Referenced by ExecReScan().