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 1641 of file nodeMergejoin.c.

1642 {
1643  MJ1_printf("ExecEndMergeJoin: %s\n",
1644  "ending node processing");
1645 
1646  /*
1647  * shut down the subplans
1648  */
1649  ExecEndNode(innerPlanState(node));
1650  ExecEndNode(outerPlanState(node));
1651 
1652  MJ1_printf("ExecEndMergeJoin: %s\n",
1653  "node processing ended");
1654 }
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:557
#define MJ1_printf(s, p)
Definition: execdebug.h:121
#define outerPlanState(node)
Definition: execnodes.h:1212
#define innerPlanState(node)
Definition: execnodes.h:1211

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

Referenced by ExecEndNode().

◆ ExecInitMergeJoin()

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

Definition at line 1444 of file nodeMergejoin.c.

1445 {
1446  MergeJoinState *mergestate;
1447  TupleDesc outerDesc,
1448  innerDesc;
1449  const TupleTableSlotOps *innerOps;
1450 
1451  /* check for unsupported flags */
1452  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
1453 
1454  MJ1_printf("ExecInitMergeJoin: %s\n",
1455  "initializing node");
1456 
1457  /*
1458  * create state structure
1459  */
1460  mergestate = makeNode(MergeJoinState);
1461  mergestate->js.ps.plan = (Plan *) node;
1462  mergestate->js.ps.state = estate;
1463  mergestate->js.ps.ExecProcNode = ExecMergeJoin;
1464  mergestate->js.jointype = node->join.jointype;
1465  mergestate->mj_ConstFalseJoin = false;
1466 
1467  /*
1468  * Miscellaneous initialization
1469  *
1470  * create expression context for node
1471  */
1472  ExecAssignExprContext(estate, &mergestate->js.ps);
1473 
1474  /*
1475  * we need two additional econtexts in which we can compute the join
1476  * expressions from the left and right input tuples. The node's regular
1477  * econtext won't do because it gets reset too often.
1478  */
1479  mergestate->mj_OuterEContext = CreateExprContext(estate);
1480  mergestate->mj_InnerEContext = CreateExprContext(estate);
1481 
1482  /*
1483  * initialize child nodes
1484  *
1485  * inner child must support MARK/RESTORE, unless we have detected that we
1486  * don't need that. Note that skip_mark_restore must never be set if
1487  * there are non-mergeclause joinquals, since the logic wouldn't work.
1488  */
1489  Assert(node->join.joinqual == NIL || !node->skip_mark_restore);
1490  mergestate->mj_SkipMarkRestore = node->skip_mark_restore;
1491 
1492  outerPlanState(mergestate) = ExecInitNode(outerPlan(node), estate, eflags);
1493  outerDesc = ExecGetResultType(outerPlanState(mergestate));
1494  innerPlanState(mergestate) = ExecInitNode(innerPlan(node), estate,
1495  mergestate->mj_SkipMarkRestore ?
1496  eflags :
1497  (eflags | EXEC_FLAG_MARK));
1498  innerDesc = ExecGetResultType(innerPlanState(mergestate));
1499 
1500  /*
1501  * For certain types of inner child nodes, it is advantageous to issue
1502  * MARK every time we advance past an inner tuple we will never return to.
1503  * For other types, MARK on a tuple we cannot return to is a waste of
1504  * cycles. Detect which case applies and set mj_ExtraMarks if we want to
1505  * issue "unnecessary" MARK calls.
1506  *
1507  * Currently, only Material wants the extra MARKs, and it will be helpful
1508  * only if eflags doesn't specify REWIND.
1509  *
1510  * Note that for IndexScan and IndexOnlyScan, it is *necessary* that we
1511  * not set mj_ExtraMarks; otherwise we might attempt to set a mark before
1512  * the first inner tuple, which they do not support.
1513  */
1514  if (IsA(innerPlan(node), Material) &&
1515  (eflags & EXEC_FLAG_REWIND) == 0 &&
1516  !mergestate->mj_SkipMarkRestore)
1517  mergestate->mj_ExtraMarks = true;
1518  else
1519  mergestate->mj_ExtraMarks = false;
1520 
1521  /*
1522  * Initialize result slot, type and projection.
1523  */
1524  ExecInitResultTupleSlotTL(&mergestate->js.ps, &TTSOpsVirtual);
1525  ExecAssignProjectionInfo(&mergestate->js.ps, NULL);
1526 
1527  /*
1528  * tuple table initialization
1529  */
1530  innerOps = ExecGetResultSlotOps(innerPlanState(mergestate), NULL);
1531  mergestate->mj_MarkedTupleSlot = ExecInitExtraTupleSlot(estate, innerDesc,
1532  innerOps);
1533 
1534  /*
1535  * initialize child expressions
1536  */
1537  mergestate->js.ps.qual =
1538  ExecInitQual(node->join.plan.qual, (PlanState *) mergestate);
1539  mergestate->js.joinqual =
1540  ExecInitQual(node->join.joinqual, (PlanState *) mergestate);
1541  /* mergeclauses are handled below */
1542 
1543  /*
1544  * detect whether we need only consider the first matching inner tuple
1545  */
1546  mergestate->js.single_match = (node->join.inner_unique ||
1547  node->join.jointype == JOIN_SEMI);
1548 
1549  /* set up null tuples for outer joins, if needed */
1550  switch (node->join.jointype)
1551  {
1552  case JOIN_INNER:
1553  case JOIN_SEMI:
1554  mergestate->mj_FillOuter = false;
1555  mergestate->mj_FillInner = false;
1556  break;
1557  case JOIN_LEFT:
1558  case JOIN_ANTI:
1559  mergestate->mj_FillOuter = true;
1560  mergestate->mj_FillInner = false;
1561  mergestate->mj_NullInnerTupleSlot =
1562  ExecInitNullTupleSlot(estate, innerDesc, &TTSOpsVirtual);
1563  break;
1564  case JOIN_RIGHT:
1565  case JOIN_RIGHT_ANTI:
1566  mergestate->mj_FillOuter = false;
1567  mergestate->mj_FillInner = true;
1568  mergestate->mj_NullOuterTupleSlot =
1569  ExecInitNullTupleSlot(estate, outerDesc, &TTSOpsVirtual);
1570 
1571  /*
1572  * Can't handle right, right-anti or full join with non-constant
1573  * extra joinclauses. This should have been caught by planner.
1574  */
1575  if (!check_constant_qual(node->join.joinqual,
1576  &mergestate->mj_ConstFalseJoin))
1577  ereport(ERROR,
1578  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1579  errmsg("RIGHT JOIN is only supported with merge-joinable join conditions")));
1580  break;
1581  case JOIN_FULL:
1582  mergestate->mj_FillOuter = true;
1583  mergestate->mj_FillInner = true;
1584  mergestate->mj_NullOuterTupleSlot =
1585  ExecInitNullTupleSlot(estate, outerDesc, &TTSOpsVirtual);
1586  mergestate->mj_NullInnerTupleSlot =
1587  ExecInitNullTupleSlot(estate, innerDesc, &TTSOpsVirtual);
1588 
1589  /*
1590  * Can't handle right, right-anti or full join with non-constant
1591  * extra joinclauses. This should have been caught by planner.
1592  */
1593  if (!check_constant_qual(node->join.joinqual,
1594  &mergestate->mj_ConstFalseJoin))
1595  ereport(ERROR,
1596  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1597  errmsg("FULL JOIN is only supported with merge-joinable join conditions")));
1598  break;
1599  default:
1600  elog(ERROR, "unrecognized join type: %d",
1601  (int) node->join.jointype);
1602  }
1603 
1604  /*
1605  * preprocess the merge clauses
1606  */
1607  mergestate->mj_NumClauses = list_length(node->mergeclauses);
1608  mergestate->mj_Clauses = MJExamineQuals(node->mergeclauses,
1609  node->mergeFamilies,
1610  node->mergeCollations,
1611  node->mergeStrategies,
1612  node->mergeNullsFirst,
1613  (PlanState *) mergestate);
1614 
1615  /*
1616  * initialize join state
1617  */
1618  mergestate->mj_JoinState = EXEC_MJ_INITIALIZE_OUTER;
1619  mergestate->mj_MatchedOuter = false;
1620  mergestate->mj_MatchedInner = false;
1621  mergestate->mj_OuterTupleSlot = NULL;
1622  mergestate->mj_InnerTupleSlot = NULL;
1623 
1624  /*
1625  * initialization successful
1626  */
1627  MJ1_printf("ExecInitMergeJoin: %s\n",
1628  "node initialized");
1629 
1630  return mergestate;
1631 }
#define Assert(condition)
Definition: c.h:858
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:224
#define ereport(elevel,...)
Definition: elog.h:149
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:220
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:142
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:84
TupleTableSlot * ExecInitNullTupleSlot(EState *estate, TupleDesc tupType, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1934
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1918
void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1886
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:493
const TupleTableSlotOps * ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
Definition: execUtils.c:502
ExprContext * CreateExprContext(EState *estate)
Definition: execUtils.c:304
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:483
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition: execUtils.c:538
#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, int *mergestrategies, bool *mergenullsfirst, PlanState *parent)
#define EXEC_MJ_INITIALIZE_OUTER
static TupleTableSlot * ExecMergeJoin(PlanState *pstate)
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:181
#define outerPlan(node)
Definition: plannodes.h:182
JoinType jointype
Definition: execnodes.h:2113
PlanState ps
Definition: execnodes.h:2112
ExprState * joinqual
Definition: execnodes.h:2116
bool single_match
Definition: execnodes.h:2114
List * joinqual
Definition: plannodes.h:793
JoinType jointype
Definition: plannodes.h:791
bool inner_unique
Definition: plannodes.h:792
bool mj_MatchedOuter
Definition: execnodes.h:2171
bool mj_SkipMarkRestore
Definition: execnodes.h:2166
bool mj_ConstFalseJoin
Definition: execnodes.h:2168
TupleTableSlot * mj_MarkedTupleSlot
Definition: execnodes.h:2175
TupleTableSlot * mj_NullInnerTupleSlot
Definition: execnodes.h:2177
ExprContext * mj_InnerEContext
Definition: execnodes.h:2179
TupleTableSlot * mj_NullOuterTupleSlot
Definition: execnodes.h:2176
bool mj_ExtraMarks
Definition: execnodes.h:2167
MergeJoinClause mj_Clauses
Definition: execnodes.h:2164
bool mj_MatchedInner
Definition: execnodes.h:2172
TupleTableSlot * mj_InnerTupleSlot
Definition: execnodes.h:2174
ExprContext * mj_OuterEContext
Definition: execnodes.h:2178
JoinState js
Definition: execnodes.h:2162
TupleTableSlot * mj_OuterTupleSlot
Definition: execnodes.h:2173
List * mergeclauses
Definition: plannodes.h:841
Join join
Definition: plannodes.h:835
bool skip_mark_restore
Definition: plannodes.h:838
ExprState * qual
Definition: execnodes.h:1137
Plan * plan
Definition: execnodes.h:1116
EState * state
Definition: execnodes.h:1118
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:1122

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 1657 of file nodeMergejoin.c.

1658 {
1661 
1663 
1665  node->mj_MatchedOuter = false;
1666  node->mj_MatchedInner = false;
1667  node->mj_OuterTupleSlot = NULL;
1668  node->mj_InnerTupleSlot = NULL;
1669 
1670  /*
1671  * if chgParam of subnodes is not null then plans will be re-scanned by
1672  * first ExecProcNode.
1673  */
1674  if (outerPlan->chgParam == NULL)
1676  if (innerPlan->chgParam == NULL)
1678 }
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().