PostgreSQL Source Code  git master
nodeHashjoin.h File Reference
#include "access/parallel.h"
#include "nodes/execnodes.h"
#include "storage/buffile.h"
Include dependency graph for nodeHashjoin.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

HashJoinStateExecInitHashJoin (HashJoin *node, EState *estate, int eflags)
 
void ExecEndHashJoin (HashJoinState *node)
 
void ExecReScanHashJoin (HashJoinState *node)
 
void ExecShutdownHashJoin (HashJoinState *node)
 
void ExecHashJoinEstimate (HashJoinState *state, ParallelContext *pcxt)
 
void ExecHashJoinInitializeDSM (HashJoinState *state, ParallelContext *pcxt)
 
void ExecHashJoinReInitializeDSM (HashJoinState *state, ParallelContext *pcxt)
 
void ExecHashJoinInitializeWorker (HashJoinState *state, ParallelWorkerContext *pwcxt)
 
void ExecHashJoinSaveTuple (MinimalTuple tuple, uint32 hashvalue, BufFile **fileptr)
 

Function Documentation

◆ ExecEndHashJoin()

void ExecEndHashJoin ( HashJoinState node)

Definition at line 759 of file nodeHashjoin.c.

References ExecClearTuple(), ExecEndNode(), ExecFreeExprContext(), ExecHashTableDestroy(), HashJoinState::hj_HashTable, HashJoinState::hj_HashTupleSlot, HashJoinState::hj_OuterTupleSlot, innerPlanState, HashJoinState::js, outerPlanState, JoinState::ps, and PlanState::ps_ResultTupleSlot.

Referenced by ExecEndNode().

760 {
761  /*
762  * Free hash table
763  */
764  if (node->hj_HashTable)
765  {
767  node->hj_HashTable = NULL;
768  }
769 
770  /*
771  * Free the exprcontext
772  */
773  ExecFreeExprContext(&node->js.ps);
774 
775  /*
776  * clean out the tuple table
777  */
781 
782  /*
783  * clean up subtrees
784  */
787 }
PlanState ps
Definition: execnodes.h:1621
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:539
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:475
TupleTableSlot * hj_OuterTupleSlot
Definition: execnodes.h:1734
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:561
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:901
#define outerPlanState(node)
Definition: execnodes.h:914
TupleTableSlot * hj_HashTupleSlot
Definition: execnodes.h:1735
HashJoinTable hj_HashTable
Definition: execnodes.h:1729
#define innerPlanState(node)
Definition: execnodes.h:913
JoinState js
Definition: execnodes.h:1724
void ExecHashTableDestroy(HashJoinTable hashtable)
Definition: nodeHash.c:848

◆ ExecHashJoinEstimate()

void ExecHashJoinEstimate ( HashJoinState state,
ParallelContext pcxt 
)

Definition at line 1417 of file nodeHashjoin.c.

References ParallelContext::estimator, shm_toc_estimate_chunk, and shm_toc_estimate_keys.

Referenced by ExecParallelEstimate().

1418 {
1420  shm_toc_estimate_keys(&pcxt->estimator, 1);
1421 }
shm_toc_estimator estimator
Definition: parallel.h:41
#define shm_toc_estimate_chunk(e, sz)
Definition: shm_toc.h:51
#define shm_toc_estimate_keys(e, cnt)
Definition: shm_toc.h:53

◆ ExecHashJoinInitializeDSM()

void ExecHashJoinInitializeDSM ( HashJoinState state,
ParallelContext pcxt 
)

Definition at line 1424 of file nodeHashjoin.c.

References BarrierInit(), ParallelHashJoinState::batches, ParallelHashJoinState::build_barrier, ParallelHashJoinState::chunk_work_queue, ParallelHashJoinState::distributor, ExecParallelHashJoin(), ExecSetExecProcNode(), ParallelHashJoinState::fileset, ParallelHashJoinState::grow_batches_barrier, ParallelHashJoinState::grow_buckets_barrier, ParallelHashJoinState::growth, innerPlanState, InvalidDsaPointer, HashJoinState::js, ParallelHashJoinState::lock, LWLockInitialize(), LWTRANCHE_PARALLEL_HASH_JOIN, ParallelHashJoinState::nbatch, ParallelHashJoinState::nbuckets, ParallelHashJoinState::nparticipants, ParallelContext::nworkers, ParallelHashJoinState::old_batches, HashState::parallel_state, pg_atomic_init_u32(), PHJ_GROWTH_OK, PlanState::plan, Plan::plan_node_id, JoinState::ps, ParallelContext::seg, SharedFileSetInit(), shm_toc_allocate(), shm_toc_insert(), ParallelHashJoinState::space_allowed, ParallelContext::toc, and ParallelHashJoinState::total_tuples.

Referenced by ExecParallelInitializeDSM().

1425 {
1426  int plan_node_id = state->js.ps.plan->plan_node_id;
1427  HashState *hashNode;
1428  ParallelHashJoinState *pstate;
1429 
1430  /*
1431  * Disable shared hash table mode if we failed to create a real DSM
1432  * segment, because that means that we don't have a DSA area to work with.
1433  */
1434  if (pcxt->seg == NULL)
1435  return;
1436 
1438 
1439  /*
1440  * Set up the state needed to coordinate access to the shared hash
1441  * table(s), using the plan node ID as the toc key.
1442  */
1443  pstate = shm_toc_allocate(pcxt->toc, sizeof(ParallelHashJoinState));
1444  shm_toc_insert(pcxt->toc, plan_node_id, pstate);
1445 
1446  /*
1447  * Set up the shared hash join state with no batches initially.
1448  * ExecHashTableCreate() will prepare at least one later and set nbatch
1449  * and space_allowed.
1450  */
1451  pstate->nbatch = 0;
1452  pstate->space_allowed = 0;
1453  pstate->batches = InvalidDsaPointer;
1454  pstate->old_batches = InvalidDsaPointer;
1455  pstate->nbuckets = 0;
1456  pstate->growth = PHJ_GROWTH_OK;
1458  pg_atomic_init_u32(&pstate->distributor, 0);
1459  pstate->nparticipants = pcxt->nworkers + 1;
1460  pstate->total_tuples = 0;
1461  LWLockInitialize(&pstate->lock,
1463  BarrierInit(&pstate->build_barrier, 0);
1464  BarrierInit(&pstate->grow_batches_barrier, 0);
1465  BarrierInit(&pstate->grow_buckets_barrier, 0);
1466 
1467  /* Set up the space we'll use for shared temporary files. */
1468  SharedFileSetInit(&pstate->fileset, pcxt->seg);
1469 
1470  /* Initialize the shared state in the hash node. */
1471  hashNode = (HashState *) innerPlanState(state);
1472  hashNode->parallel_state = pstate;
1473 }
struct ParallelHashJoinState * parallel_state
Definition: execnodes.h:2067
dsa_pointer chunk_work_queue
Definition: hashjoin.h:242
#define InvalidDsaPointer
Definition: dsa.h:78
void BarrierInit(Barrier *barrier, int participants)
Definition: barrier.c:100
void SharedFileSetInit(SharedFileSet *fileset, dsm_segment *seg)
Definition: sharedfileset.c:47
PlanState ps
Definition: execnodes.h:1621
dsm_segment * seg
Definition: parallel.h:42
int plan_node_id
Definition: plannodes.h:143
SharedFileSet fileset
Definition: hashjoin.h:253
Barrier grow_buckets_barrier
Definition: hashjoin.h:250
dsa_pointer batches
Definition: hashjoin.h:236
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:676
void ExecSetExecProcNode(PlanState *node, ExecProcNodeMtd function)
Definition: execProcnode.c:406
Plan * plan
Definition: execnodes.h:868
ParallelHashGrowth growth
Definition: hashjoin.h:241
dsa_pointer old_batches
Definition: hashjoin.h:237
static TupleTableSlot * ExecParallelHashJoin(PlanState *pstate)
Definition: nodeHashjoin.c:575
void * shm_toc_allocate(shm_toc *toc, Size nbytes)
Definition: shm_toc.c:88
pg_atomic_uint32 distributor
Definition: hashjoin.h:251
void shm_toc_insert(shm_toc *toc, uint64 key, void *address)
Definition: shm_toc.c:171
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:234
#define innerPlanState(node)
Definition: execnodes.h:913
JoinState js
Definition: execnodes.h:1724
Barrier grow_batches_barrier
Definition: hashjoin.h:249
shm_toc * toc
Definition: parallel.h:44

◆ ExecHashJoinInitializeWorker()

void ExecHashJoinInitializeWorker ( HashJoinState state,
ParallelWorkerContext pwcxt 
)

Definition at line 1515 of file nodeHashjoin.c.

References ExecParallelHashJoin(), ExecSetExecProcNode(), ParallelHashJoinState::fileset, innerPlanState, HashJoinState::js, HashState::parallel_state, PlanState::plan, Plan::plan_node_id, JoinState::ps, ParallelWorkerContext::seg, SharedFileSetAttach(), shm_toc_lookup(), and ParallelWorkerContext::toc.

Referenced by ExecParallelInitializeWorker().

1517 {
1518  HashState *hashNode;
1519  int plan_node_id = state->js.ps.plan->plan_node_id;
1520  ParallelHashJoinState *pstate =
1521  shm_toc_lookup(pwcxt->toc, plan_node_id, false);
1522 
1523  /* Attach to the space for shared temporary files. */
1524  SharedFileSetAttach(&pstate->fileset, pwcxt->seg);
1525 
1526  /* Attach to the shared state in the hash node. */
1527  hashNode = (HashState *) innerPlanState(state);
1528  hashNode->parallel_state = pstate;
1529 
1531 }
struct ParallelHashJoinState * parallel_state
Definition: execnodes.h:2067
PlanState ps
Definition: execnodes.h:1621
int plan_node_id
Definition: plannodes.h:143
SharedFileSet fileset
Definition: hashjoin.h:253
void ExecSetExecProcNode(PlanState *node, ExecProcNodeMtd function)
Definition: execProcnode.c:406
Plan * plan
Definition: execnodes.h:868
static TupleTableSlot * ExecParallelHashJoin(PlanState *pstate)
Definition: nodeHashjoin.c:575
void SharedFileSetAttach(SharedFileSet *fileset, dsm_segment *seg)
Definition: sharedfileset.c:76
#define innerPlanState(node)
Definition: execnodes.h:913
JoinState js
Definition: execnodes.h:1724
void * shm_toc_lookup(shm_toc *toc, uint64 key, bool noError)
Definition: shm_toc.c:232
dsm_segment * seg
Definition: parallel.h:52

◆ ExecHashJoinReInitializeDSM()

void ExecHashJoinReInitializeDSM ( HashJoinState state,
ParallelContext pcxt 
)

Definition at line 1482 of file nodeHashjoin.c.

References BarrierInit(), ParallelHashJoinState::build_barrier, ExecHashTableDetach(), ExecHashTableDetachBatch(), ParallelHashJoinState::fileset, HashJoinState::hj_HashTable, HashJoinState::js, PlanState::plan, Plan::plan_node_id, JoinState::ps, SharedFileSetDeleteAll(), shm_toc_lookup(), and ParallelContext::toc.

Referenced by ExecParallelReInitializeDSM().

1483 {
1484  int plan_node_id = state->js.ps.plan->plan_node_id;
1485  ParallelHashJoinState *pstate =
1486  shm_toc_lookup(cxt->toc, plan_node_id, false);
1487 
1488  /*
1489  * It would be possible to reuse the shared hash table in single-batch
1490  * cases by resetting and then fast-forwarding build_barrier to
1491  * PHJ_BUILD_DONE and batch 0's batch_barrier to PHJ_BATCH_PROBING, but
1492  * currently shared hash tables are already freed by now (by the last
1493  * participant to detach from the batch). We could consider keeping it
1494  * around for single-batch joins. We'd also need to adjust
1495  * finalize_plan() so that it doesn't record a dummy dependency for
1496  * Parallel Hash nodes, preventing the rescan optimization. For now we
1497  * don't try.
1498  */
1499 
1500  /* Detach, freeing any remaining shared memory. */
1501  if (state->hj_HashTable != NULL)
1502  {
1505  }
1506 
1507  /* Clear any shared batch files. */
1508  SharedFileSetDeleteAll(&pstate->fileset);
1509 
1510  /* Reset build_barrier to PHJ_BUILD_ELECTING so we can go around again. */
1511  BarrierInit(&pstate->build_barrier, 0);
1512 }
void BarrierInit(Barrier *barrier, int participants)
Definition: barrier.c:100
PlanState ps
Definition: execnodes.h:1621
void ExecHashTableDetachBatch(HashJoinTable hashtable)
Definition: nodeHash.c:3055
void ExecHashTableDetach(HashJoinTable hashtable)
Definition: nodeHash.c:3112
int plan_node_id
Definition: plannodes.h:143
SharedFileSet fileset
Definition: hashjoin.h:253
Plan * plan
Definition: execnodes.h:868
void SharedFileSetDeleteAll(SharedFileSet *fileset)
HashJoinTable hj_HashTable
Definition: execnodes.h:1729
JoinState js
Definition: execnodes.h:1724
void * shm_toc_lookup(shm_toc *toc, uint64 key, bool noError)
Definition: shm_toc.c:232

◆ ExecHashJoinSaveTuple()

void ExecHashJoinSaveTuple ( MinimalTuple  tuple,
uint32  hashvalue,
BufFile **  fileptr 
)

Definition at line 1210 of file nodeHashjoin.c.

References BufFileCreateTemp(), BufFileWrite(), ereport, errcode_for_file_access(), errmsg(), ERROR, and MinimalTupleData::t_len.

Referenced by ExecHashIncreaseNumBatches(), ExecHashJoinImpl(), ExecHashRemoveNextSkewBucket(), and ExecHashTableInsert().

1212 {
1213  BufFile *file = *fileptr;
1214  size_t written;
1215 
1216  if (file == NULL)
1217  {
1218  /* First write to this batch file, so open it. */
1219  file = BufFileCreateTemp(false);
1220  *fileptr = file;
1221  }
1222 
1223  written = BufFileWrite(file, (void *) &hashvalue, sizeof(uint32));
1224  if (written != sizeof(uint32))
1225  ereport(ERROR,
1227  errmsg("could not write to hash-join temporary file: %m")));
1228 
1229  written = BufFileWrite(file, (void *) tuple, tuple->t_len);
1230  if (written != tuple->t_len)
1231  ereport(ERROR,
1233  errmsg("could not write to hash-join temporary file: %m")));
1234 }
#define ERROR
Definition: elog.h:43
BufFile * BufFileCreateTemp(bool interXact)
Definition: buffile.c:182
int errcode_for_file_access(void)
Definition: elog.c:598
unsigned int uint32
Definition: c.h:314
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797
size_t BufFileWrite(BufFile *file, void *ptr, size_t size)
Definition: buffile.c:601

◆ ExecInitHashJoin()

HashJoinState* ExecInitHashJoin ( HashJoin node,
EState estate,
int  eflags 
)

Definition at line 591 of file nodeHashjoin.c.

References OpExpr::args, Assert, elog, ERROR, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, ExecAssignExprContext(), ExecAssignProjectionInfo(), ExecGetResultType(), ExecHashJoin(), ExecInitExpr(), ExecInitExtraTupleSlot(), ExecInitNode(), ExecInitNullTupleSlot(), ExecInitQual(), ExecInitResultTupleSlotTL(), PlanState::ExecProcNode, HashJoin::hashclauses, HJ_BUILD_HASHTABLE, HashJoinState::hj_HashTupleSlot, HashJoinState::hj_NullInnerTupleSlot, HashJoinState::hj_NullOuterTupleSlot, HashJoinState::hj_OuterTupleSlot, Join::inner_unique, innerPlan, innerPlanState, INVALID_SKEW_BUCKET_NO, HashJoin::join, JOIN_ANTI, JOIN_FULL, JOIN_INNER, JOIN_LEFT, JOIN_RIGHT, JOIN_SEMI, Join::joinqual, Join::jointype, JoinState::jointype, HashJoinState::js, lappend(), lappend_oid(), lfirst_node, linitial, lsecond, makeNode, NIL, OpExpr::opno, outerPlan, outerPlanState, Join::plan, PlanState::plan, JoinState::ps, HashState::ps, PlanState::ps_ResultTupleSlot, Plan::qual, PlanState::qual, JoinState::single_match, and PlanState::state.

Referenced by ExecInitNode().

592 {
593  HashJoinState *hjstate;
594  Plan *outerNode;
595  Hash *hashNode;
596  List *lclauses;
597  List *rclauses;
598  List *hoperators;
599  TupleDesc outerDesc, innerDesc;
600  ListCell *l;
601 
602  /* check for unsupported flags */
603  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
604 
605  /*
606  * create state structure
607  */
608  hjstate = makeNode(HashJoinState);
609  hjstate->js.ps.plan = (Plan *) node;
610  hjstate->js.ps.state = estate;
611 
612  /*
613  * See ExecHashJoinInitializeDSM() and ExecHashJoinInitializeWorker()
614  * where this function may be replaced with a parallel version, if we
615  * managed to launch a parallel query.
616  */
617  hjstate->js.ps.ExecProcNode = ExecHashJoin;
618  hjstate->js.jointype = node->join.jointype;
619 
620  /*
621  * Miscellaneous initialization
622  *
623  * create expression context for node
624  */
625  ExecAssignExprContext(estate, &hjstate->js.ps);
626 
627  /*
628  * initialize child nodes
629  *
630  * Note: we could suppress the REWIND flag for the inner input, which
631  * would amount to betting that the hash will be a single batch. Not
632  * clear if this would be a win or not.
633  */
634  outerNode = outerPlan(node);
635  hashNode = (Hash *) innerPlan(node);
636 
637  outerPlanState(hjstate) = ExecInitNode(outerNode, estate, eflags);
638  outerDesc = ExecGetResultType(outerPlanState(hjstate));
639  innerPlanState(hjstate) = ExecInitNode((Plan *) hashNode, estate, eflags);
640  innerDesc = ExecGetResultType(innerPlanState(hjstate));
641 
642  /*
643  * Initialize result slot, type and projection.
644  */
645  ExecInitResultTupleSlotTL(estate, &hjstate->js.ps);
646  ExecAssignProjectionInfo(&hjstate->js.ps, NULL);
647 
648  /*
649  * tuple table initialization
650  */
651  hjstate->hj_OuterTupleSlot = ExecInitExtraTupleSlot(estate, outerDesc);
652 
653  /*
654  * detect whether we need only consider the first matching inner tuple
655  */
656  hjstate->js.single_match = (node->join.inner_unique ||
657  node->join.jointype == JOIN_SEMI);
658 
659  /* set up null tuples for outer joins, if needed */
660  switch (node->join.jointype)
661  {
662  case JOIN_INNER:
663  case JOIN_SEMI:
664  break;
665  case JOIN_LEFT:
666  case JOIN_ANTI:
667  hjstate->hj_NullInnerTupleSlot =
668  ExecInitNullTupleSlot(estate, innerDesc);
669  break;
670  case JOIN_RIGHT:
671  hjstate->hj_NullOuterTupleSlot =
672  ExecInitNullTupleSlot(estate, outerDesc);
673  break;
674  case JOIN_FULL:
675  hjstate->hj_NullOuterTupleSlot =
676  ExecInitNullTupleSlot(estate, outerDesc);
677  hjstate->hj_NullInnerTupleSlot =
678  ExecInitNullTupleSlot(estate, innerDesc);
679  break;
680  default:
681  elog(ERROR, "unrecognized join type: %d",
682  (int) node->join.jointype);
683  }
684 
685  /*
686  * now for some voodoo. our temporary tuple slot is actually the result
687  * tuple slot of the Hash node (which is our inner plan). we can do this
688  * because Hash nodes don't return tuples via ExecProcNode() -- instead
689  * the hash join node uses ExecScanHashBucket() to get at the contents of
690  * the hash table. -cim 6/9/91
691  */
692  {
693  HashState *hashstate = (HashState *) innerPlanState(hjstate);
694  TupleTableSlot *slot = hashstate->ps.ps_ResultTupleSlot;
695 
696  hjstate->hj_HashTupleSlot = slot;
697  }
698 
699  /*
700  * initialize child expressions
701  */
702  hjstate->js.ps.qual =
703  ExecInitQual(node->join.plan.qual, (PlanState *) hjstate);
704  hjstate->js.joinqual =
705  ExecInitQual(node->join.joinqual, (PlanState *) hjstate);
706  hjstate->hashclauses =
707  ExecInitQual(node->hashclauses, (PlanState *) hjstate);
708 
709  /*
710  * initialize hash-specific info
711  */
712  hjstate->hj_HashTable = NULL;
713  hjstate->hj_FirstOuterTupleSlot = NULL;
714 
715  hjstate->hj_CurHashValue = 0;
716  hjstate->hj_CurBucketNo = 0;
718  hjstate->hj_CurTuple = NULL;
719 
720  /*
721  * Deconstruct the hash clauses into outer and inner argument values, so
722  * that we can evaluate those subexpressions separately. Also make a list
723  * of the hash operator OIDs, in preparation for looking up the hash
724  * functions to use.
725  */
726  lclauses = NIL;
727  rclauses = NIL;
728  hoperators = NIL;
729  foreach(l, node->hashclauses)
730  {
731  OpExpr *hclause = lfirst_node(OpExpr, l);
732 
733  lclauses = lappend(lclauses, ExecInitExpr(linitial(hclause->args),
734  (PlanState *) hjstate));
735  rclauses = lappend(rclauses, ExecInitExpr(lsecond(hclause->args),
736  (PlanState *) hjstate));
737  hoperators = lappend_oid(hoperators, hclause->opno);
738  }
739  hjstate->hj_OuterHashKeys = lclauses;
740  hjstate->hj_InnerHashKeys = rclauses;
741  hjstate->hj_HashOperators = hoperators;
742  /* child Hash node needs to evaluate inner hash keys, too */
743  ((HashState *) innerPlanState(hjstate))->hashkeys = rclauses;
744 
745  hjstate->hj_JoinState = HJ_BUILD_HASHTABLE;
746  hjstate->hj_MatchedOuter = false;
747  hjstate->hj_OuterNotEmpty = false;
748 
749  return hjstate;
750 }
JoinType jointype
Definition: execnodes.h:1622
#define NIL
Definition: pg_list.h:69
List * qual
Definition: plannodes.h:145
#define INVALID_SKEW_BUCKET_NO
Definition: hashjoin.h:109
TupleTableSlot * hj_NullInnerTupleSlot
Definition: execnodes.h:1737
ExprState * joinqual
Definition: execnodes.h:1625
PlanState ps
Definition: execnodes.h:1621
List * hashclauses
Definition: plannodes.h:728
bool single_match
Definition: execnodes.h:1623
bool hj_MatchedOuter
Definition: execnodes.h:1740
EState * state
Definition: execnodes.h:870
TupleTableSlot * hj_OuterTupleSlot
Definition: execnodes.h:1734
List * hj_OuterHashKeys
Definition: execnodes.h:1726
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
TupleTableSlot * hj_FirstOuterTupleSlot
Definition: execnodes.h:1738
#define lsecond(l)
Definition: pg_list.h:116
Join join
Definition: plannodes.h:727
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc)
Definition: execTuples.c:910
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:204
JoinType jointype
Definition: plannodes.h:669
uint32 hj_CurHashValue
Definition: execnodes.h:1730
int hj_CurSkewBucketNo
Definition: execnodes.h:1732
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:901
TupleTableSlot * ExecInitNullTupleSlot(EState *estate, TupleDesc tupType)
Definition: execTuples.c:924
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
TupleTableSlot * hj_NullOuterTupleSlot
Definition: execnodes.h:1736
#define EXEC_FLAG_BACKWARD
Definition: executor.h:61
#define lfirst_node(type, lc)
Definition: pg_list.h:109
#define outerPlanState(node)
Definition: execnodes.h:914
#define innerPlan(node)
Definition: plannodes.h:173
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition: execUtils.c:453
HashJoinTuple hj_CurTuple
Definition: execnodes.h:1733
PlanState ps
Definition: execnodes.h:2058
List * hj_HashOperators
Definition: execnodes.h:1728
#define outerPlan(node)
Definition: plannodes.h:174
List * lappend(List *list, void *datum)
Definition: list.c:128
int hj_CurBucketNo
Definition: execnodes.h:1731
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:874
void ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate)
Definition: execTuples.c:870
Plan * plan
Definition: execnodes.h:868
#define makeNode(_type_)
Definition: nodes.h:561
bool hj_OuterNotEmpty
Definition: execnodes.h:1741
#define Assert(condition)
Definition: c.h:688
#define EXEC_FLAG_MARK
Definition: executor.h:62
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:425
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:435
ExprState * qual
Definition: execnodes.h:886
TupleTableSlot * hj_HashTupleSlot
Definition: execnodes.h:1735
List * hj_InnerHashKeys
Definition: execnodes.h:1727
#define HJ_BUILD_HASHTABLE
Definition: nodeHashjoin.c:124
HashJoinTable hj_HashTable
Definition: execnodes.h:1729
static TupleTableSlot * ExecHashJoin(PlanState *pstate)
Definition: nodeHashjoin.c:559
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:118
Oid opno
Definition: primnodes.h:496
#define elog
Definition: elog.h:219
bool inner_unique
Definition: plannodes.h:670
List * args
Definition: primnodes.h:502
#define innerPlanState(node)
Definition: execnodes.h:913
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:139
Definition: pg_list.h:45
JoinState js
Definition: execnodes.h:1724
List * joinqual
Definition: plannodes.h:671
ExprState * hashclauses
Definition: execnodes.h:1725
Plan plan
Definition: plannodes.h:668

◆ ExecReScanHashJoin()

void ExecReScanHashJoin ( HashJoinState node)

Definition at line 1290 of file nodeHashjoin.c.

References PlanState::chgParam, ExecHashTableDestroy(), ExecHashTableResetMatchFlags(), ExecReScan(), HJ_BUILD_HASHTABLE, HashJoinState::hj_CurBucketNo, HashJoinState::hj_CurHashValue, HashJoinState::hj_CurSkewBucketNo, HashJoinState::hj_CurTuple, HJ_FILL_INNER, HashJoinState::hj_FirstOuterTupleSlot, HashJoinState::hj_HashTable, HashJoinState::hj_JoinState, HashJoinState::hj_MatchedOuter, HJ_NEED_NEW_OUTER, HashJoinState::hj_OuterNotEmpty, INVALID_SKEW_BUCKET_NO, HashJoinState::js, PlanState::lefttree, HashJoinTableData::nbatch, JoinState::ps, and PlanState::righttree.

Referenced by ExecReScan().

1291 {
1292  /*
1293  * In a multi-batch join, we currently have to do rescans the hard way,
1294  * primarily because batch temp files may have already been released. But
1295  * if it's a single-batch join, and there is no parameter change for the
1296  * inner subnode, then we can just re-use the existing hash table without
1297  * rebuilding it.
1298  */
1299  if (node->hj_HashTable != NULL)
1300  {
1301  if (node->hj_HashTable->nbatch == 1 &&
1302  node->js.ps.righttree->chgParam == NULL)
1303  {
1304  /*
1305  * Okay to reuse the hash table; needn't rescan inner, either.
1306  *
1307  * However, if it's a right/full join, we'd better reset the
1308  * inner-tuple match flags contained in the table.
1309  */
1310  if (HJ_FILL_INNER(node))
1312 
1313  /*
1314  * Also, we need to reset our state about the emptiness of the
1315  * outer relation, so that the new scan of the outer will update
1316  * it correctly if it turns out to be empty this time. (There's no
1317  * harm in clearing it now because ExecHashJoin won't need the
1318  * info. In the other cases, where the hash table doesn't exist
1319  * or we are destroying it, we leave this state alone because
1320  * ExecHashJoin will need it the first time through.)
1321  */
1322  node->hj_OuterNotEmpty = false;
1323 
1324  /* ExecHashJoin can skip the BUILD_HASHTABLE step */
1326  }
1327  else
1328  {
1329  /* must destroy and rebuild hash table */
1331  node->hj_HashTable = NULL;
1333 
1334  /*
1335  * if chgParam of subnode is not null then plan will be re-scanned
1336  * by first ExecProcNode.
1337  */
1338  if (node->js.ps.righttree->chgParam == NULL)
1339  ExecReScan(node->js.ps.righttree);
1340  }
1341  }
1342 
1343  /* Always reset intra-tuple state */
1344  node->hj_CurHashValue = 0;
1345  node->hj_CurBucketNo = 0;
1347  node->hj_CurTuple = NULL;
1348 
1349  node->hj_MatchedOuter = false;
1350  node->hj_FirstOuterTupleSlot = NULL;
1351 
1352  /*
1353  * if chgParam of subnode is not null then plan will be re-scanned by
1354  * first ExecProcNode.
1355  */
1356  if (node->js.ps.lefttree->chgParam == NULL)
1357  ExecReScan(node->js.ps.lefttree);
1358 }
#define INVALID_SKEW_BUCKET_NO
Definition: hashjoin.h:109
PlanState ps
Definition: execnodes.h:1621
void ExecReScan(PlanState *node)
Definition: execAmi.c:76
bool hj_MatchedOuter
Definition: execnodes.h:1740
struct PlanState * righttree
Definition: execnodes.h:888
TupleTableSlot * hj_FirstOuterTupleSlot
Definition: execnodes.h:1738
struct PlanState * lefttree
Definition: execnodes.h:887
#define HJ_FILL_INNER(hjstate)
Definition: nodeHashjoin.c:134
uint32 hj_CurHashValue
Definition: execnodes.h:1730
int hj_CurSkewBucketNo
Definition: execnodes.h:1732
HashJoinTuple hj_CurTuple
Definition: execnodes.h:1733
Bitmapset * chgParam
Definition: execnodes.h:896
int hj_CurBucketNo
Definition: execnodes.h:1731
bool hj_OuterNotEmpty
Definition: execnodes.h:1741
#define HJ_NEED_NEW_OUTER
Definition: nodeHashjoin.c:125
#define HJ_BUILD_HASHTABLE
Definition: nodeHashjoin.c:124
HashJoinTable hj_HashTable
Definition: execnodes.h:1729
void ExecHashTableResetMatchFlags(HashJoinTable hashtable)
Definition: nodeHash.c:2142
JoinState js
Definition: execnodes.h:1724
void ExecHashTableDestroy(HashJoinTable hashtable)
Definition: nodeHash.c:848

◆ ExecShutdownHashJoin()

void ExecShutdownHashJoin ( HashJoinState node)

Definition at line 1361 of file nodeHashjoin.c.

References ExecHashTableDetach(), ExecHashTableDetachBatch(), and HashJoinState::hj_HashTable.

Referenced by ExecShutdownNode().

1362 {
1363  if (node->hj_HashTable)
1364  {
1365  /*
1366  * Detach from shared state before DSM memory goes away. This makes
1367  * sure that we don't have any pointers into DSM memory by the time
1368  * ExecEndHashJoin runs.
1369  */
1372  }
1373 }
void ExecHashTableDetachBatch(HashJoinTable hashtable)
Definition: nodeHash.c:3055
void ExecHashTableDetach(HashJoinTable hashtable)
Definition: nodeHash.c:3112
HashJoinTable hj_HashTable
Definition: execnodes.h:1729