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 1632 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().

1633 {
1634  MJ1_printf("ExecEndMergeJoin: %s\n",
1635  "ending node processing");
1636 
1637  /*
1638  * Free the exprcontext
1639  */
1640  ExecFreeExprContext(&node->js.ps);
1641 
1642  /*
1643  * clean out the tuple table
1644  */
1647 
1648  /*
1649  * shut down the subplans
1650  */
1651  ExecEndNode(innerPlanState(node));
1652  ExecEndNode(outerPlanState(node));
1653 
1654  MJ1_printf("ExecEndMergeJoin: %s\n",
1655  "node processing ended");
1656 }
#define MJ1_printf(s, p)
Definition: execdebug.h:119
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
PlanState ps
Definition: execnodes.h:1830
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:537
TupleTableSlot * mj_MarkedTupleSlot
Definition: execnodes.h:1893
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:614
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:977
#define outerPlanState(node)
Definition: execnodes.h:1033
JoinState js
Definition: execnodes.h:1880
#define innerPlanState(node)
Definition: execnodes.h:1032

◆ 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(), 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_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, PlanState::state, and TTSOpsVirtual.

Referenced by ExecInitNode().

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

◆ ExecReScanMergeJoin()

void ExecReScanMergeJoin ( MergeJoinState node)

Definition at line 1659 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().

1660 {
1662 
1664  node->mj_MatchedOuter = false;
1665  node->mj_MatchedInner = false;
1666  node->mj_OuterTupleSlot = NULL;
1667  node->mj_InnerTupleSlot = NULL;
1668 
1669  /*
1670  * if chgParam of subnodes is not null then plans will be re-scanned by
1671  * first ExecProcNode.
1672  */
1673  if (node->js.ps.lefttree->chgParam == NULL)
1674  ExecReScan(node->js.ps.lefttree);
1675  if (node->js.ps.righttree->chgParam == NULL)
1676  ExecReScan(node->js.ps.righttree);
1677 
1678 }
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
PlanState ps
Definition: execnodes.h:1830
void ExecReScan(PlanState *node)
Definition: execAmi.c:75
TupleTableSlot * mj_MarkedTupleSlot
Definition: execnodes.h:1893
struct PlanState * righttree
Definition: execnodes.h:962
struct PlanState * lefttree
Definition: execnodes.h:961
bool mj_MatchedOuter
Definition: execnodes.h:1889
bool mj_MatchedInner
Definition: execnodes.h:1890
#define EXEC_MJ_INITIALIZE_OUTER
Bitmapset * chgParam
Definition: execnodes.h:971
JoinState js
Definition: execnodes.h:1880
TupleTableSlot * mj_InnerTupleSlot
Definition: execnodes.h:1892
TupleTableSlot * mj_OuterTupleSlot
Definition: execnodes.h:1891