PostgreSQL Source Code  git master
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 1628 of file nodeMergejoin.c.

References ExecClearTuple(), ExecEndNode(), ExecFreeExprContext(), innerPlanState, MergeJoinState::js, MJ1_printf, MergeJoinState::mj_MarkedTupleSlot, outerPlanState, JoinState::ps, and PlanState::ps_ResultTupleSlot.

Referenced by ExecEndNode().

1629 {
1630  MJ1_printf("ExecEndMergeJoin: %s\n",
1631  "ending node processing");
1632 
1633  /*
1634  * Free the exprcontext
1635  */
1636  ExecFreeExprContext(&node->js.ps);
1637 
1638  /*
1639  * clean out the tuple table
1640  */
1643 
1644  /*
1645  * shut down the subplans
1646  */
1647  ExecEndNode(innerPlanState(node));
1648  ExecEndNode(outerPlanState(node));
1649 
1650  MJ1_printf("ExecEndMergeJoin: %s\n",
1651  "node processing ended");
1652 }
#define MJ1_printf(s, p)
Definition: execdebug.h:119
PlanState ps
Definition: execnodes.h:1686
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:539
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:475
TupleTableSlot * mj_MarkedTupleSlot
Definition: execnodes.h:1749
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:566
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:945
#define outerPlanState(node)
Definition: execnodes.h:965
JoinState js
Definition: execnodes.h:1736
#define innerPlanState(node)
Definition: execnodes.h:964

◆ ExecInitMergeJoin()

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

Definition at line 1436 of file nodeMergejoin.c.

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(), 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_SEMI, Join::joinqual, Join::jointype, JoinState::jointype, MergeJoinState::js, list_length(), makeNode, MergeJoin::mergeclauses, MergeJoin::mergeCollations, MergeJoin::mergeFamilies, MergeJoin::mergeNullsFirst, MergeJoin::mergeStrategies, MJ1_printf, MergeJoinState::mj_ConstFalseJoin, MergeJoinState::mj_ExtraMarks, MergeJoinState::mj_InnerEContext, MergeJoinState::mj_MarkedTupleSlot, MergeJoinState::mj_OuterEContext, MergeJoinState::mj_SkipMarkRestore, MJExamineQuals(), NIL, outerPlan, outerPlanState, Join::plan, PlanState::plan, JoinState::ps, Plan::qual, PlanState::qual, MergeJoin::skip_mark_restore, and PlanState::state.

Referenced by ExecInitNode().

1437 {
1438  MergeJoinState *mergestate;
1439  TupleDesc outerDesc, innerDesc;
1440 
1441  /* check for unsupported flags */
1442  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
1443 
1444  MJ1_printf("ExecInitMergeJoin: %s\n",
1445  "initializing node");
1446 
1447  /*
1448  * create state structure
1449  */
1450  mergestate = makeNode(MergeJoinState);
1451  mergestate->js.ps.plan = (Plan *) node;
1452  mergestate->js.ps.state = estate;
1453  mergestate->js.ps.ExecProcNode = ExecMergeJoin;
1454  mergestate->js.jointype = node->join.jointype;
1455  mergestate->mj_ConstFalseJoin = false;
1456 
1457  /*
1458  * Miscellaneous initialization
1459  *
1460  * create expression context for node
1461  */
1462  ExecAssignExprContext(estate, &mergestate->js.ps);
1463 
1464  /*
1465  * we need two additional econtexts in which we can compute the join
1466  * expressions from the left and right input tuples. The node's regular
1467  * econtext won't do because it gets reset too often.
1468  */
1469  mergestate->mj_OuterEContext = CreateExprContext(estate);
1470  mergestate->mj_InnerEContext = CreateExprContext(estate);
1471 
1472  /*
1473  * initialize child nodes
1474  *
1475  * inner child must support MARK/RESTORE, unless we have detected that we
1476  * don't need that. Note that skip_mark_restore must never be set if
1477  * there are non-mergeclause joinquals, since the logic wouldn't work.
1478  */
1479  Assert(node->join.joinqual == NIL || !node->skip_mark_restore);
1480  mergestate->mj_SkipMarkRestore = node->skip_mark_restore;
1481 
1482  outerPlanState(mergestate) = ExecInitNode(outerPlan(node), estate, eflags);
1483  outerDesc = ExecGetResultType(outerPlanState(mergestate));
1484  innerPlanState(mergestate) = ExecInitNode(innerPlan(node), estate,
1485  mergestate->mj_SkipMarkRestore ?
1486  eflags :
1487  (eflags | EXEC_FLAG_MARK));
1488  innerDesc = ExecGetResultType(innerPlanState(mergestate));
1489 
1490  /*
1491  * For certain types of inner child nodes, it is advantageous to issue
1492  * MARK every time we advance past an inner tuple we will never return to.
1493  * For other types, MARK on a tuple we cannot return to is a waste of
1494  * cycles. Detect which case applies and set mj_ExtraMarks if we want to
1495  * issue "unnecessary" MARK calls.
1496  *
1497  * Currently, only Material wants the extra MARKs, and it will be helpful
1498  * only if eflags doesn't specify REWIND.
1499  *
1500  * Note that for IndexScan and IndexOnlyScan, it is *necessary* that we
1501  * not set mj_ExtraMarks; otherwise we might attempt to set a mark before
1502  * the first inner tuple, which they do not support.
1503  */
1504  if (IsA(innerPlan(node), Material) &&
1505  (eflags & EXEC_FLAG_REWIND) == 0 &&
1506  !mergestate->mj_SkipMarkRestore)
1507  mergestate->mj_ExtraMarks = true;
1508  else
1509  mergestate->mj_ExtraMarks = false;
1510 
1511  /*
1512  * Initialize result slot, type and projection.
1513  */
1514  ExecInitResultTupleSlotTL(estate, &mergestate->js.ps);
1515  ExecAssignProjectionInfo(&mergestate->js.ps, NULL);
1516 
1517  /*
1518  * tuple table initialization
1519  */
1520  mergestate->mj_MarkedTupleSlot = ExecInitExtraTupleSlot(estate, innerDesc);
1521 
1522  /*
1523  * initialize child expressions
1524  */
1525  mergestate->js.ps.qual =
1526  ExecInitQual(node->join.plan.qual, (PlanState *) mergestate);
1527  mergestate->js.joinqual =
1528  ExecInitQual(node->join.joinqual, (PlanState *) mergestate);
1529  /* mergeclauses are handled below */
1530 
1531  /*
1532  * detect whether we need only consider the first matching inner tuple
1533  */
1534  mergestate->js.single_match = (node->join.inner_unique ||
1535  node->join.jointype == JOIN_SEMI);
1536 
1537  /* set up null tuples for outer joins, if needed */
1538  switch (node->join.jointype)
1539  {
1540  case JOIN_INNER:
1541  case JOIN_SEMI:
1542  mergestate->mj_FillOuter = false;
1543  mergestate->mj_FillInner = false;
1544  break;
1545  case JOIN_LEFT:
1546  case JOIN_ANTI:
1547  mergestate->mj_FillOuter = true;
1548  mergestate->mj_FillInner = false;
1549  mergestate->mj_NullInnerTupleSlot =
1550  ExecInitNullTupleSlot(estate, innerDesc);
1551  break;
1552  case JOIN_RIGHT:
1553  mergestate->mj_FillOuter = false;
1554  mergestate->mj_FillInner = true;
1555  mergestate->mj_NullOuterTupleSlot =
1556  ExecInitNullTupleSlot(estate, outerDesc);
1557 
1558  /*
1559  * Can't handle right or full join with non-constant extra
1560  * joinclauses. This should have been caught by planner.
1561  */
1562  if (!check_constant_qual(node->join.joinqual,
1563  &mergestate->mj_ConstFalseJoin))
1564  ereport(ERROR,
1565  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1566  errmsg("RIGHT JOIN is only supported with merge-joinable join conditions")));
1567  break;
1568  case JOIN_FULL:
1569  mergestate->mj_FillOuter = true;
1570  mergestate->mj_FillInner = true;
1571  mergestate->mj_NullOuterTupleSlot =
1572  ExecInitNullTupleSlot(estate, outerDesc);
1573  mergestate->mj_NullInnerTupleSlot =
1574  ExecInitNullTupleSlot(estate, innerDesc);
1575 
1576  /*
1577  * Can't handle right or full join with non-constant extra
1578  * joinclauses. This should have been caught by planner.
1579  */
1580  if (!check_constant_qual(node->join.joinqual,
1581  &mergestate->mj_ConstFalseJoin))
1582  ereport(ERROR,
1583  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1584  errmsg("FULL JOIN is only supported with merge-joinable join conditions")));
1585  break;
1586  default:
1587  elog(ERROR, "unrecognized join type: %d",
1588  (int) node->join.jointype);
1589  }
1590 
1591  /*
1592  * preprocess the merge clauses
1593  */
1594  mergestate->mj_NumClauses = list_length(node->mergeclauses);
1595  mergestate->mj_Clauses = MJExamineQuals(node->mergeclauses,
1596  node->mergeFamilies,
1597  node->mergeCollations,
1598  node->mergeStrategies,
1599  node->mergeNullsFirst,
1600  (PlanState *) mergestate);
1601 
1602  /*
1603  * initialize join state
1604  */
1605  mergestate->mj_JoinState = EXEC_MJ_INITIALIZE_OUTER;
1606  mergestate->mj_MatchedOuter = false;
1607  mergestate->mj_MatchedInner = false;
1608  mergestate->mj_OuterTupleSlot = NULL;
1609  mergestate->mj_InnerTupleSlot = NULL;
1610 
1611  /*
1612  * initialization successful
1613  */
1614  MJ1_printf("ExecInitMergeJoin: %s\n",
1615  "node initialized");
1616 
1617  return mergestate;
1618 }
JoinType jointype
Definition: execnodes.h:1687
#define NIL
Definition: pg_list.h:69
List * qual
Definition: plannodes.h:147
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
#define MJ1_printf(s, p)
Definition: execdebug.h:119
ExprState * joinqual
Definition: execnodes.h:1690
ExprContext * mj_InnerEContext
Definition: execnodes.h:1753
bool mj_ConstFalseJoin
Definition: execnodes.h:1742
PlanState ps
Definition: execnodes.h:1686
bool single_match
Definition: execnodes.h:1688
TupleTableSlot * mj_MarkedTupleSlot
Definition: execnodes.h:1749
TupleTableSlot * mj_NullInnerTupleSlot
Definition: execnodes.h:1751
int errcode(int sqlerrcode)
Definition: elog.c:575
EState * state
Definition: execnodes.h:913
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc)
Definition: execTuples.c:931
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:205
List * mergeclauses
Definition: plannodes.h:725
JoinType jointype
Definition: plannodes.h:681
bool mj_MatchedOuter
Definition: execnodes.h:1745
TupleTableSlot * ExecInitNullTupleSlot(EState *estate, TupleDesc tupType)
Definition: execTuples.c:945
static MergeJoinClause MJExamineQuals(List *mergeclauses, Oid *mergefamilies, Oid *mergecollations, int *mergestrategies, bool *mergenullsfirst, PlanState *parent)
bool skip_mark_restore
Definition: plannodes.h:724
#define ERROR
Definition: elog.h:43
bool mj_MatchedInner
Definition: execnodes.h:1746
#define EXEC_FLAG_BACKWARD
Definition: executor.h:60
#define outerPlanState(node)
Definition: execnodes.h:965
#define innerPlan(node)
Definition: plannodes.h:175
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition: execUtils.c:456
MergeJoinClause mj_Clauses
Definition: execnodes.h:1738
#define EXEC_FLAG_REWIND
Definition: executor.h:59
#define ereport(elevel, rest)
Definition: elog.h:122
#define EXEC_MJ_INITIALIZE_OUTER
#define outerPlan(node)
Definition: plannodes.h:176
static bool check_constant_qual(List *qual, bool *is_const_false)
bool mj_SkipMarkRestore
Definition: execnodes.h:1740
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:917
Oid * mergeFamilies
Definition: plannodes.h:727
Oid * mergeCollations
Definition: plannodes.h:728
void ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate)
Definition: execTuples.c:890
Plan * plan
Definition: execnodes.h:911
JoinState js
Definition: execnodes.h:1736
bool * mergeNullsFirst
Definition: plannodes.h:730
#define makeNode(_type_)
Definition: nodes.h:565
int * mergeStrategies
Definition: plannodes.h:729
#define Assert(condition)
Definition: c.h:699
#define EXEC_FLAG_MARK
Definition: executor.h:61
TupleTableSlot * mj_InnerTupleSlot
Definition: execnodes.h:1748
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:428
ExprContext * mj_OuterEContext
Definition: execnodes.h:1752
static int list_length(const List *l)
Definition: pg_list.h:89
TupleTableSlot * mj_NullOuterTupleSlot
Definition: execnodes.h:1750
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:438
ExprState * qual
Definition: execnodes.h:929
static TupleTableSlot * ExecMergeJoin(PlanState *pstate)
int errmsg(const char *fmt,...)
Definition: elog.c:797
Join join
Definition: plannodes.h:723
ExprContext * CreateExprContext(EState *estate)
Definition: execUtils.c:228
#define elog
Definition: elog.h:219
bool inner_unique
Definition: plannodes.h:682
bool mj_ExtraMarks
Definition: execnodes.h:1741
#define innerPlanState(node)
Definition: execnodes.h:964
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:139
List * joinqual
Definition: plannodes.h:683
TupleTableSlot * mj_OuterTupleSlot
Definition: execnodes.h:1747
Plan plan
Definition: plannodes.h:680

◆ ExecReScanMergeJoin()

void ExecReScanMergeJoin ( MergeJoinState node)

Definition at line 1655 of file nodeMergejoin.c.

References PlanState::chgParam, EXEC_MJ_INITIALIZE_OUTER, ExecClearTuple(), ExecReScan(), MergeJoinState::js, PlanState::lefttree, MergeJoinState::mj_InnerTupleSlot, MergeJoinState::mj_JoinState, MergeJoinState::mj_MarkedTupleSlot, MergeJoinState::mj_MatchedInner, MergeJoinState::mj_MatchedOuter, MergeJoinState::mj_OuterTupleSlot, JoinState::ps, and PlanState::righttree.

Referenced by ExecReScan().

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 (node->js.ps.lefttree->chgParam == NULL)
1670  ExecReScan(node->js.ps.lefttree);
1671  if (node->js.ps.righttree->chgParam == NULL)
1672  ExecReScan(node->js.ps.righttree);
1673 
1674 }
PlanState ps
Definition: execnodes.h:1686
void ExecReScan(PlanState *node)
Definition: execAmi.c:76
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:475
TupleTableSlot * mj_MarkedTupleSlot
Definition: execnodes.h:1749
struct PlanState * righttree
Definition: execnodes.h:931
struct PlanState * lefttree
Definition: execnodes.h:930
bool mj_MatchedOuter
Definition: execnodes.h:1745
bool mj_MatchedInner
Definition: execnodes.h:1746
#define EXEC_MJ_INITIALIZE_OUTER
Bitmapset * chgParam
Definition: execnodes.h:940
JoinState js
Definition: execnodes.h:1736
TupleTableSlot * mj_InnerTupleSlot
Definition: execnodes.h:1748
TupleTableSlot * mj_OuterTupleSlot
Definition: execnodes.h:1747