PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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)
extern

Definition at line 1638 of file nodeMergejoin.c.

1639{
1640 MJ1_printf("ExecEndMergeJoin: %s\n",
1641 "ending node processing");
1642
1643 /*
1644 * shut down the subplans
1645 */
1648
1649 MJ1_printf("ExecEndMergeJoin: %s\n",
1650 "node processing ended");
1651}
void ExecEndNode(PlanState *node)
#define MJ1_printf(s, p)
Definition execdebug.h:121
#define outerPlanState(node)
Definition execnodes.h:1273
#define innerPlanState(node)
Definition execnodes.h:1272

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

Referenced by ExecEndNode().

◆ ExecInitMergeJoin()

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

Definition at line 1441 of file nodeMergejoin.c.

1442{
1445 innerDesc;
1447
1448 /* check for unsupported flags */
1449 Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
1450
1451 MJ1_printf("ExecInitMergeJoin: %s\n",
1452 "initializing node");
1453
1454 /*
1455 * create state structure
1456 */
1458 mergestate->js.ps.plan = (Plan *) node;
1459 mergestate->js.ps.state = estate;
1460 mergestate->js.ps.ExecProcNode = ExecMergeJoin;
1461 mergestate->js.jointype = node->join.jointype;
1462 mergestate->mj_ConstFalseJoin = false;
1463
1464 /*
1465 * Miscellaneous initialization
1466 *
1467 * create expression context for node
1468 */
1469 ExecAssignExprContext(estate, &mergestate->js.ps);
1470
1471 /*
1472 * we need two additional econtexts in which we can compute the join
1473 * expressions from the left and right input tuples. The node's regular
1474 * econtext won't do because it gets reset too often.
1475 */
1476 mergestate->mj_OuterEContext = CreateExprContext(estate);
1477 mergestate->mj_InnerEContext = CreateExprContext(estate);
1478
1479 /*
1480 * initialize child nodes
1481 *
1482 * inner child must support MARK/RESTORE, unless we have detected that we
1483 * don't need that. Note that skip_mark_restore must never be set if
1484 * there are non-mergeclause joinquals, since the logic wouldn't work.
1485 */
1486 Assert(node->join.joinqual == NIL || !node->skip_mark_restore);
1487 mergestate->mj_SkipMarkRestore = node->skip_mark_restore;
1488
1489 outerPlanState(mergestate) = ExecInitNode(outerPlan(node), estate, eflags);
1492 mergestate->mj_SkipMarkRestore ?
1493 eflags :
1494 (eflags | EXEC_FLAG_MARK));
1496
1497 /*
1498 * For certain types of inner child nodes, it is advantageous to issue
1499 * MARK every time we advance past an inner tuple we will never return to.
1500 * For other types, MARK on a tuple we cannot return to is a waste of
1501 * cycles. Detect which case applies and set mj_ExtraMarks if we want to
1502 * issue "unnecessary" MARK calls.
1503 *
1504 * Currently, only Material wants the extra MARKs, and it will be helpful
1505 * only if eflags doesn't specify REWIND.
1506 *
1507 * Note that for IndexScan and IndexOnlyScan, it is *necessary* that we
1508 * not set mj_ExtraMarks; otherwise we might attempt to set a mark before
1509 * the first inner tuple, which they do not support.
1510 */
1511 if (IsA(innerPlan(node), Material) &&
1512 (eflags & EXEC_FLAG_REWIND) == 0 &&
1513 !mergestate->mj_SkipMarkRestore)
1514 mergestate->mj_ExtraMarks = true;
1515 else
1516 mergestate->mj_ExtraMarks = false;
1517
1518 /*
1519 * Initialize result slot, type and projection.
1520 */
1523
1524 /*
1525 * tuple table initialization
1526 */
1528 mergestate->mj_MarkedTupleSlot = ExecInitExtraTupleSlot(estate, innerDesc,
1529 innerOps);
1530
1531 /*
1532 * initialize child expressions
1533 */
1534 mergestate->js.ps.qual =
1535 ExecInitQual(node->join.plan.qual, (PlanState *) mergestate);
1536 mergestate->js.joinqual =
1538 /* mergeclauses are handled below */
1539
1540 /*
1541 * detect whether we need only consider the first matching inner tuple
1542 */
1543 mergestate->js.single_match = (node->join.inner_unique ||
1544 node->join.jointype == JOIN_SEMI);
1545
1546 /* set up null tuples for outer joins, if needed */
1547 switch (node->join.jointype)
1548 {
1549 case JOIN_INNER:
1550 case JOIN_SEMI:
1551 mergestate->mj_FillOuter = false;
1552 mergestate->mj_FillInner = false;
1553 break;
1554 case JOIN_LEFT:
1555 case JOIN_ANTI:
1556 mergestate->mj_FillOuter = true;
1557 mergestate->mj_FillInner = false;
1558 mergestate->mj_NullInnerTupleSlot =
1560 break;
1561 case JOIN_RIGHT:
1562 case JOIN_RIGHT_ANTI:
1563 mergestate->mj_FillOuter = false;
1564 mergestate->mj_FillInner = true;
1565 mergestate->mj_NullOuterTupleSlot =
1567
1568 /*
1569 * Can't handle right, right-anti or full join with non-constant
1570 * extra joinclauses. This should have been caught by planner.
1571 */
1573 &mergestate->mj_ConstFalseJoin))
1574 ereport(ERROR,
1576 errmsg("RIGHT JOIN is only supported with merge-joinable join conditions")));
1577 break;
1578 case JOIN_FULL:
1579 mergestate->mj_FillOuter = true;
1580 mergestate->mj_FillInner = true;
1581 mergestate->mj_NullOuterTupleSlot =
1583 mergestate->mj_NullInnerTupleSlot =
1585
1586 /*
1587 * Can't handle right, right-anti or full join with non-constant
1588 * extra joinclauses. This should have been caught by planner.
1589 */
1591 &mergestate->mj_ConstFalseJoin))
1592 ereport(ERROR,
1594 errmsg("FULL JOIN is only supported with merge-joinable join conditions")));
1595 break;
1596 default:
1597 elog(ERROR, "unrecognized join type: %d",
1598 (int) node->join.jointype);
1599 }
1600
1601 /*
1602 * preprocess the merge clauses
1603 */
1604 mergestate->mj_NumClauses = list_length(node->mergeclauses);
1605 mergestate->mj_Clauses = MJExamineQuals(node->mergeclauses,
1606 node->mergeFamilies,
1607 node->mergeCollations,
1608 node->mergeReversals,
1609 node->mergeNullsFirst,
1610 (PlanState *) mergestate);
1611
1612 /*
1613 * initialize join state
1614 */
1615 mergestate->mj_JoinState = EXEC_MJ_INITIALIZE_OUTER;
1616 mergestate->mj_MatchedOuter = false;
1617 mergestate->mj_MatchedInner = false;
1618 mergestate->mj_OuterTupleSlot = NULL;
1619 mergestate->mj_InnerTupleSlot = NULL;
1620
1621 /*
1622 * initialization successful
1623 */
1624 MJ1_printf("ExecInitMergeJoin: %s\n",
1625 "node initialized");
1626
1627 return mergestate;
1628}
#define Assert(condition)
Definition c.h:945
int errcode(int sqlerrcode)
Definition elog.c:874
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define ereport(elevel,...)
Definition elog.h:150
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition execExpr.c:250
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
const TupleTableSlotOps TTSOpsVirtual
Definition execTuples.c:84
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)
Definition execUtils.c:500
ExprContext * CreateExprContext(EState *estate)
Definition execUtils.c:312
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition execUtils.c:490
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition execUtils.c:588
const TupleTableSlotOps * ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
Definition execUtils.c:509
#define EXEC_FLAG_BACKWARD
Definition executor.h:70
#define EXEC_FLAG_REWIND
Definition executor.h:69
#define EXEC_FLAG_MARK
Definition executor.h:71
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:164
#define makeNode(_type_)
Definition nodes.h:161
@ JOIN_SEMI
Definition nodes.h:317
@ JOIN_FULL
Definition nodes.h:305
@ JOIN_INNER
Definition nodes.h:303
@ JOIN_RIGHT
Definition nodes.h:306
@ JOIN_LEFT
Definition nodes.h:304
@ JOIN_RIGHT_ANTI
Definition nodes.h:320
@ JOIN_ANTI
Definition nodes.h:318
static char * errmsg
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:264
#define outerPlan(node)
Definition plannodes.h:265
static int fb(int x)
List * joinqual
Definition plannodes.h:988
JoinType jointype
Definition plannodes.h:985
bool inner_unique
Definition plannodes.h:986
List * mergeclauses
Definition plannodes.h:1039
bool skip_mark_restore
Definition plannodes.h:1036

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(), fb(), Join::inner_unique, innerPlan, innerPlanState, IsA, MergeJoin::join, JOIN_ANTI, JOIN_FULL, JOIN_INNER, JOIN_LEFT, JOIN_RIGHT, JOIN_RIGHT_ANTI, JOIN_SEMI, Join::joinqual, Join::jointype, list_length(), makeNode, MergeJoin::mergeclauses, MJ1_printf, MJExamineQuals(), NIL, outerPlan, outerPlanState, MergeJoin::skip_mark_restore, and TTSOpsVirtual.

Referenced by ExecInitNode().

◆ ExecReScanMergeJoin()

void ExecReScanMergeJoin ( MergeJoinState node)
extern

Definition at line 1654 of file nodeMergejoin.c.

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

References EXEC_MJ_INITIALIZE_OUTER, ExecClearTuple(), ExecReScan(), fb(), 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().