PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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

void ExecEndMergeJoin ( MergeJoinState node)

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

1630 {
1631  MJ1_printf("ExecEndMergeJoin: %s\n",
1632  "ending node processing");
1633 
1634  /*
1635  * Free the exprcontext
1636  */
1637  ExecFreeExprContext(&node->js.ps);
1638 
1639  /*
1640  * clean out the tuple table
1641  */
1644 
1645  /*
1646  * shut down the subplans
1647  */
1648  ExecEndNode(innerPlanState(node));
1649  ExecEndNode(outerPlanState(node));
1650 
1651  MJ1_printf("ExecEndMergeJoin: %s\n",
1652  "node processing ended");
1653 }
#define MJ1_printf(s, p)
Definition: execdebug.h:119
PlanState ps
Definition: execnodes.h:1590
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:523
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
TupleTableSlot * mj_MarkedTupleSlot
Definition: execnodes.h:1653
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:521
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:880
#define outerPlanState(node)
Definition: execnodes.h:893
JoinState js
Definition: execnodes.h:1640
#define innerPlanState(node)
Definition: execnodes.h:892
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(), ExecAssignResultTypeFromTL(), ExecGetResultType(), ExecInitExtraTupleSlot(), ExecInitNode(), ExecInitNullTupleSlot(), ExecInitQual(), ExecInitResultTupleSlot(), ExecMergeJoin(), PlanState::ExecProcNode, ExecSetSlotDescriptor(), Join::inner_unique, innerPlan, innerPlanState, IsA, MergeJoin::join, JOIN_ANTI, JOIN_FULL, JOIN_INNER, JOIN_LEFT, JOIN_RIGHT, JOIN_SEMI, Join::joinqual, JoinState::joinqual, Join::jointype, JoinState::jointype, MergeJoinState::js, list_length(), makeNode, MergeJoin::mergeclauses, MergeJoin::mergeCollations, MergeJoin::mergeFamilies, MergeJoin::mergeNullsFirst, MergeJoin::mergeStrategies, 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, Join::plan, PlanState::plan, JoinState::ps, Plan::qual, PlanState::qual, JoinState::single_match, MergeJoin::skip_mark_restore, and PlanState::state.

Referenced by ExecInitNode().

1437 {
1438  MergeJoinState *mergestate;
1439 
1440  /* check for unsupported flags */
1441  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
1442 
1443  MJ1_printf("ExecInitMergeJoin: %s\n",
1444  "initializing node");
1445 
1446  /*
1447  * create state structure
1448  */
1449  mergestate = makeNode(MergeJoinState);
1450  mergestate->js.ps.plan = (Plan *) node;
1451  mergestate->js.ps.state = estate;
1452  mergestate->js.ps.ExecProcNode = ExecMergeJoin;
1453 
1454  /*
1455  * Miscellaneous initialization
1456  *
1457  * create expression context for node
1458  */
1459  ExecAssignExprContext(estate, &mergestate->js.ps);
1460 
1461  /*
1462  * we need two additional econtexts in which we can compute the join
1463  * expressions from the left and right input tuples. The node's regular
1464  * econtext won't do because it gets reset too often.
1465  */
1466  mergestate->mj_OuterEContext = CreateExprContext(estate);
1467  mergestate->mj_InnerEContext = CreateExprContext(estate);
1468 
1469  /*
1470  * initialize child expressions
1471  */
1472  mergestate->js.ps.qual =
1473  ExecInitQual(node->join.plan.qual, (PlanState *) mergestate);
1474  mergestate->js.jointype = node->join.jointype;
1475  mergestate->js.joinqual =
1476  ExecInitQual(node->join.joinqual, (PlanState *) mergestate);
1477  mergestate->mj_ConstFalseJoin = false;
1478  /* mergeclauses are handled below */
1479 
1480  /*
1481  * initialize child nodes
1482  *
1483  * inner child must support MARK/RESTORE, unless we have detected that we
1484  * don't need that. Note that skip_mark_restore must never be set if
1485  * there are non-mergeclause joinquals, since the logic wouldn't work.
1486  */
1487  Assert(node->join.joinqual == NIL || !node->skip_mark_restore);
1488  mergestate->mj_SkipMarkRestore = node->skip_mark_restore;
1489 
1490  outerPlanState(mergestate) = ExecInitNode(outerPlan(node), estate, eflags);
1491  innerPlanState(mergestate) = ExecInitNode(innerPlan(node), estate,
1492  mergestate->mj_SkipMarkRestore ?
1493  eflags :
1494  (eflags | EXEC_FLAG_MARK));
1495 
1496  /*
1497  * For certain types of inner child nodes, it is advantageous to issue
1498  * MARK every time we advance past an inner tuple we will never return to.
1499  * For other types, MARK on a tuple we cannot return to is a waste of
1500  * cycles. Detect which case applies and set mj_ExtraMarks if we want to
1501  * issue "unnecessary" MARK calls.
1502  *
1503  * Currently, only Material wants the extra MARKs, and it will be helpful
1504  * only if eflags doesn't specify REWIND.
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  * tuple table initialization
1515  */
1516  ExecInitResultTupleSlot(estate, &mergestate->js.ps);
1517 
1518  mergestate->mj_MarkedTupleSlot = ExecInitExtraTupleSlot(estate);
1520  ExecGetResultType(innerPlanState(mergestate)));
1521 
1522  /*
1523  * detect whether we need only consider the first matching inner tuple
1524  */
1525  mergestate->js.single_match = (node->join.inner_unique ||
1526  node->join.jointype == JOIN_SEMI);
1527 
1528  /* set up null tuples for outer joins, if needed */
1529  switch (node->join.jointype)
1530  {
1531  case JOIN_INNER:
1532  case JOIN_SEMI:
1533  mergestate->mj_FillOuter = false;
1534  mergestate->mj_FillInner = false;
1535  break;
1536  case JOIN_LEFT:
1537  case JOIN_ANTI:
1538  mergestate->mj_FillOuter = true;
1539  mergestate->mj_FillInner = false;
1540  mergestate->mj_NullInnerTupleSlot =
1541  ExecInitNullTupleSlot(estate,
1542  ExecGetResultType(innerPlanState(mergestate)));
1543  break;
1544  case JOIN_RIGHT:
1545  mergestate->mj_FillOuter = false;
1546  mergestate->mj_FillInner = true;
1547  mergestate->mj_NullOuterTupleSlot =
1548  ExecInitNullTupleSlot(estate,
1549  ExecGetResultType(outerPlanState(mergestate)));
1550 
1551  /*
1552  * Can't handle right or full join with non-constant extra
1553  * joinclauses. This should have been caught by planner.
1554  */
1555  if (!check_constant_qual(node->join.joinqual,
1556  &mergestate->mj_ConstFalseJoin))
1557  ereport(ERROR,
1558  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1559  errmsg("RIGHT JOIN is only supported with merge-joinable join conditions")));
1560  break;
1561  case JOIN_FULL:
1562  mergestate->mj_FillOuter = true;
1563  mergestate->mj_FillInner = true;
1564  mergestate->mj_NullOuterTupleSlot =
1565  ExecInitNullTupleSlot(estate,
1566  ExecGetResultType(outerPlanState(mergestate)));
1567  mergestate->mj_NullInnerTupleSlot =
1568  ExecInitNullTupleSlot(estate,
1569  ExecGetResultType(innerPlanState(mergestate)));
1570 
1571  /*
1572  * Can't handle right or full join with non-constant extra
1573  * 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("FULL JOIN is only supported with merge-joinable join conditions")));
1580  break;
1581  default:
1582  elog(ERROR, "unrecognized join type: %d",
1583  (int) node->join.jointype);
1584  }
1585 
1586  /*
1587  * initialize tuple type and projection info
1588  */
1589  ExecAssignResultTypeFromTL(&mergestate->js.ps);
1590  ExecAssignProjectionInfo(&mergestate->js.ps, NULL);
1591 
1592  /*
1593  * preprocess the merge clauses
1594  */
1595  mergestate->mj_NumClauses = list_length(node->mergeclauses);
1596  mergestate->mj_Clauses = MJExamineQuals(node->mergeclauses,
1597  node->mergeFamilies,
1598  node->mergeCollations,
1599  node->mergeStrategies,
1600  node->mergeNullsFirst,
1601  (PlanState *) mergestate);
1602 
1603  /*
1604  * initialize join state
1605  */
1606  mergestate->mj_JoinState = EXEC_MJ_INITIALIZE_OUTER;
1607  mergestate->mj_MatchedOuter = false;
1608  mergestate->mj_MatchedInner = false;
1609  mergestate->mj_OuterTupleSlot = NULL;
1610  mergestate->mj_InnerTupleSlot = NULL;
1611 
1612  /*
1613  * initialization successful
1614  */
1615  MJ1_printf("ExecInitMergeJoin: %s\n",
1616  "node initialized");
1617 
1618  return mergestate;
1619 }
JoinType jointype
Definition: execnodes.h:1591
#define NIL
Definition: pg_list.h:69
List * qual
Definition: plannodes.h:145
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate)
Definition: execTuples.c:852
#define MJ1_printf(s, p)
Definition: execdebug.h:119
ExprState * joinqual
Definition: execnodes.h:1594
ExprContext * mj_InnerEContext
Definition: execnodes.h:1657
bool mj_ConstFalseJoin
Definition: execnodes.h:1646
PlanState ps
Definition: execnodes.h:1590
bool single_match
Definition: execnodes.h:1592
TupleTableSlot * mj_MarkedTupleSlot
Definition: execnodes.h:1653
TupleTableSlot * mj_NullInnerTupleSlot
Definition: execnodes.h:1655
int errcode(int sqlerrcode)
Definition: elog.c:575
EState * state
Definition: execnodes.h:849
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:160
void ExecAssignResultTypeFromTL(PlanState *planstate)
Definition: execUtils.c:445
List * mergeclauses
Definition: plannodes.h:711
JoinType jointype
Definition: plannodes.h:667
bool mj_MatchedOuter
Definition: execnodes.h:1649
TupleTableSlot * ExecInitNullTupleSlot(EState *estate, TupleDesc tupType)
Definition: execTuples.c:866
static MergeJoinClause MJExamineQuals(List *mergeclauses, Oid *mergefamilies, Oid *mergecollations, int *mergestrategies, bool *mergenullsfirst, PlanState *parent)
bool skip_mark_restore
Definition: plannodes.h:710
#define ERROR
Definition: elog.h:43
void ExecInitResultTupleSlot(EState *estate, PlanState *planstate)
Definition: execTuples.c:832
bool mj_MatchedInner
Definition: execnodes.h:1650
#define EXEC_FLAG_BACKWARD
Definition: executor.h:60
#define outerPlanState(node)
Definition: execnodes.h:893
#define innerPlan(node)
Definition: plannodes.h:173
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition: execUtils.c:492
MergeJoinClause mj_Clauses
Definition: execnodes.h:1642
#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:174
static bool check_constant_qual(List *qual, bool *is_const_false)
bool mj_SkipMarkRestore
Definition: execnodes.h:1644
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:853
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:247
Oid * mergeFamilies
Definition: plannodes.h:713
Oid * mergeCollations
Definition: plannodes.h:714
Plan * plan
Definition: execnodes.h:847
JoinState js
Definition: execnodes.h:1640
bool * mergeNullsFirst
Definition: plannodes.h:716
#define makeNode(_type_)
Definition: nodes.h:558
int * mergeStrategies
Definition: plannodes.h:715
#define Assert(condition)
Definition: c.h:681
#define EXEC_FLAG_MARK
Definition: executor.h:61
TupleTableSlot * mj_InnerTupleSlot
Definition: execnodes.h:1652
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:423
ExprContext * mj_OuterEContext
Definition: execnodes.h:1656
static int list_length(const List *l)
Definition: pg_list.h:89
TupleTableSlot * mj_NullOuterTupleSlot
Definition: execnodes.h:1654
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:474
ExprState * qual
Definition: execnodes.h:865
static TupleTableSlot * ExecMergeJoin(PlanState *pstate)
int errmsg(const char *fmt,...)
Definition: elog.c:797
Join join
Definition: plannodes.h:709
ExprContext * CreateExprContext(EState *estate)
Definition: execUtils.c:223
#define elog
Definition: elog.h:219
bool inner_unique
Definition: plannodes.h:668
bool mj_ExtraMarks
Definition: execnodes.h:1645
#define innerPlanState(node)
Definition: execnodes.h:892
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:139
List * joinqual
Definition: plannodes.h:669
TupleTableSlot * mj_OuterTupleSlot
Definition: execnodes.h:1651
Plan plan
Definition: plannodes.h:666
void ExecReScanMergeJoin ( MergeJoinState node)

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

1657 {
1659 
1661  node->mj_MatchedOuter = false;
1662  node->mj_MatchedInner = false;
1663  node->mj_OuterTupleSlot = NULL;
1664  node->mj_InnerTupleSlot = NULL;
1665 
1666  /*
1667  * if chgParam of subnodes is not null then plans will be re-scanned by
1668  * first ExecProcNode.
1669  */
1670  if (node->js.ps.lefttree->chgParam == NULL)
1671  ExecReScan(node->js.ps.lefttree);
1672  if (node->js.ps.righttree->chgParam == NULL)
1673  ExecReScan(node->js.ps.righttree);
1674 
1675 }
PlanState ps
Definition: execnodes.h:1590
void ExecReScan(PlanState *node)
Definition: execAmi.c:76
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
TupleTableSlot * mj_MarkedTupleSlot
Definition: execnodes.h:1653
struct PlanState * righttree
Definition: execnodes.h:867
struct PlanState * lefttree
Definition: execnodes.h:866
bool mj_MatchedOuter
Definition: execnodes.h:1649
bool mj_MatchedInner
Definition: execnodes.h:1650
#define EXEC_MJ_INITIALIZE_OUTER
Bitmapset * chgParam
Definition: execnodes.h:875
JoinState js
Definition: execnodes.h:1640
TupleTableSlot * mj_InnerTupleSlot
Definition: execnodes.h:1652
TupleTableSlot * mj_OuterTupleSlot
Definition: execnodes.h:1651