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

747 {
748  /*
749  * Free hash table
750  */
751  if (node->hj_HashTable)
752  {
754  node->hj_HashTable = NULL;
755  }
756 
757  /*
758  * Free the exprcontext
759  */
760  ExecFreeExprContext(&node->js.ps);
761 
762  /*
763  * clean out the tuple table
764  */
768 
769  /*
770  * clean up subtrees
771  */
774 }
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
PlanState ps
Definition: execnodes.h:1830
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:537
TupleTableSlot * hj_OuterTupleSlot
Definition: execnodes.h:1942
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:614
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:977
#define outerPlanState(node)
Definition: execnodes.h:1033
TupleTableSlot * hj_HashTupleSlot
Definition: execnodes.h:1943
HashJoinTable hj_HashTable
Definition: execnodes.h:1937
#define innerPlanState(node)
Definition: execnodes.h:1032
JoinState js
Definition: execnodes.h:1932
void ExecHashTableDestroy(HashJoinTable hashtable)
Definition: nodeHash.c:853

◆ ExecHashJoinEstimate()

void ExecHashJoinEstimate ( HashJoinState state,
ParallelContext pcxt 
)

Definition at line 1412 of file nodeHashjoin.c.

References ParallelContext::estimator, shm_toc_estimate_chunk, and shm_toc_estimate_keys.

Referenced by ExecParallelEstimate().

1413 {
1415  shm_toc_estimate_keys(&pcxt->estimator, 1);
1416 }
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 1419 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().

1420 {
1421  int plan_node_id = state->js.ps.plan->plan_node_id;
1422  HashState *hashNode;
1423  ParallelHashJoinState *pstate;
1424 
1425  /*
1426  * Disable shared hash table mode if we failed to create a real DSM
1427  * segment, because that means that we don't have a DSA area to work with.
1428  */
1429  if (pcxt->seg == NULL)
1430  return;
1431 
1433 
1434  /*
1435  * Set up the state needed to coordinate access to the shared hash
1436  * table(s), using the plan node ID as the toc key.
1437  */
1438  pstate = shm_toc_allocate(pcxt->toc, sizeof(ParallelHashJoinState));
1439  shm_toc_insert(pcxt->toc, plan_node_id, pstate);
1440 
1441  /*
1442  * Set up the shared hash join state with no batches initially.
1443  * ExecHashTableCreate() will prepare at least one later and set nbatch
1444  * and space_allowed.
1445  */
1446  pstate->nbatch = 0;
1447  pstate->space_allowed = 0;
1448  pstate->batches = InvalidDsaPointer;
1449  pstate->old_batches = InvalidDsaPointer;
1450  pstate->nbuckets = 0;
1451  pstate->growth = PHJ_GROWTH_OK;
1453  pg_atomic_init_u32(&pstate->distributor, 0);
1454  pstate->nparticipants = pcxt->nworkers + 1;
1455  pstate->total_tuples = 0;
1456  LWLockInitialize(&pstate->lock,
1458  BarrierInit(&pstate->build_barrier, 0);
1459  BarrierInit(&pstate->grow_batches_barrier, 0);
1460  BarrierInit(&pstate->grow_buckets_barrier, 0);
1461 
1462  /* Set up the space we'll use for shared temporary files. */
1463  SharedFileSetInit(&pstate->fileset, pcxt->seg);
1464 
1465  /* Initialize the shared state in the hash node. */
1466  hashNode = (HashState *) innerPlanState(state);
1467  hashNode->parallel_state = pstate;
1468 }
struct ParallelHashJoinState * parallel_state
Definition: execnodes.h:2278
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:49
PlanState ps
Definition: execnodes.h:1830
dsm_segment * seg
Definition: parallel.h:42
int plan_node_id
Definition: plannodes.h:139
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:678
void ExecSetExecProcNode(PlanState *node, ExecProcNodeMtd function)
Definition: execProcnode.c:405
Plan * plan
Definition: execnodes.h:939
ParallelHashGrowth growth
Definition: hashjoin.h:241
dsa_pointer old_batches
Definition: hashjoin.h:237
static TupleTableSlot * ExecParallelHashJoin(PlanState *pstate)
Definition: nodeHashjoin.c:582
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:223
#define innerPlanState(node)
Definition: execnodes.h:1032
JoinState js
Definition: execnodes.h:1932
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 1510 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().

1512 {
1513  HashState *hashNode;
1514  int plan_node_id = state->js.ps.plan->plan_node_id;
1515  ParallelHashJoinState *pstate =
1516  shm_toc_lookup(pwcxt->toc, plan_node_id, false);
1517 
1518  /* Attach to the space for shared temporary files. */
1519  SharedFileSetAttach(&pstate->fileset, pwcxt->seg);
1520 
1521  /* Attach to the shared state in the hash node. */
1522  hashNode = (HashState *) innerPlanState(state);
1523  hashNode->parallel_state = pstate;
1524 
1526 }
struct ParallelHashJoinState * parallel_state
Definition: execnodes.h:2278
PlanState ps
Definition: execnodes.h:1830
int plan_node_id
Definition: plannodes.h:139
SharedFileSet fileset
Definition: hashjoin.h:253
void ExecSetExecProcNode(PlanState *node, ExecProcNodeMtd function)
Definition: execProcnode.c:405
Plan * plan
Definition: execnodes.h:939
static TupleTableSlot * ExecParallelHashJoin(PlanState *pstate)
Definition: nodeHashjoin.c:582
void SharedFileSetAttach(SharedFileSet *fileset, dsm_segment *seg)
Definition: sharedfileset.c:78
#define innerPlanState(node)
Definition: execnodes.h:1032
JoinState js
Definition: execnodes.h:1932
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 1477 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().

1478 {
1479  int plan_node_id = state->js.ps.plan->plan_node_id;
1480  ParallelHashJoinState *pstate =
1481  shm_toc_lookup(cxt->toc, plan_node_id, false);
1482 
1483  /*
1484  * It would be possible to reuse the shared hash table in single-batch
1485  * cases by resetting and then fast-forwarding build_barrier to
1486  * PHJ_BUILD_DONE and batch 0's batch_barrier to PHJ_BATCH_PROBING, but
1487  * currently shared hash tables are already freed by now (by the last
1488  * participant to detach from the batch). We could consider keeping it
1489  * around for single-batch joins. We'd also need to adjust
1490  * finalize_plan() so that it doesn't record a dummy dependency for
1491  * Parallel Hash nodes, preventing the rescan optimization. For now we
1492  * don't try.
1493  */
1494 
1495  /* Detach, freeing any remaining shared memory. */
1496  if (state->hj_HashTable != NULL)
1497  {
1500  }
1501 
1502  /* Clear any shared batch files. */
1503  SharedFileSetDeleteAll(&pstate->fileset);
1504 
1505  /* Reset build_barrier to PHJ_BUILD_ELECTING so we can go around again. */
1506  BarrierInit(&pstate->build_barrier, 0);
1507 }
void BarrierInit(Barrier *barrier, int participants)
Definition: barrier.c:100
PlanState ps
Definition: execnodes.h:1830
void ExecHashTableDetachBatch(HashJoinTable hashtable)
Definition: nodeHash.c:3084
void ExecHashTableDetach(HashJoinTable hashtable)
Definition: nodeHash.c:3141
int plan_node_id
Definition: plannodes.h:139
SharedFileSet fileset
Definition: hashjoin.h:253
Plan * plan
Definition: execnodes.h:939
void SharedFileSetDeleteAll(SharedFileSet *fileset)
HashJoinTable hj_HashTable
Definition: execnodes.h:1937
JoinState js
Definition: execnodes.h:1932
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 1199 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().

1201 {
1202  BufFile *file = *fileptr;
1203  size_t written;
1204 
1205  if (file == NULL)
1206  {
1207  /* First write to this batch file, so open it. */
1208  file = BufFileCreateTemp(false);
1209  *fileptr = file;
1210  }
1211 
1212  written = BufFileWrite(file, (void *) &hashvalue, sizeof(uint32));
1213  if (written != sizeof(uint32))
1214  ereport(ERROR,
1216  errmsg("could not write to hash-join temporary file: %m")));
1217 
1218  written = BufFileWrite(file, (void *) tuple, tuple->t_len);
1219  if (written != tuple->t_len)
1220  ereport(ERROR,
1222  errmsg("could not write to hash-join temporary file: %m")));
1223 }
#define ERROR
Definition: elog.h:43
BufFile * BufFileCreateTemp(bool interXact)
Definition: buffile.c:184
int errcode_for_file_access(void)
Definition: elog.c:631
unsigned int uint32
Definition: c.h:359
#define ereport(elevel, rest)
Definition: elog.h:141
int errmsg(const char *fmt,...)
Definition: elog.c:822
size_t BufFileWrite(BufFile *file, void *ptr, size_t size)
Definition: buffile.c:575

◆ ExecInitHashJoin()

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

Definition at line 598 of file nodeHashjoin.c.

References Assert, elog, ERROR, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, ExecAssignExprContext(), ExecAssignProjectionInfo(), ExecGetResultSlotOps(), ExecGetResultType(), ExecHashJoin(), ExecInitExprList(), ExecInitExtraTupleSlot(), ExecInitNode(), ExecInitNullTupleSlot(), ExecInitQual(), ExecInitResultTupleSlotTL(), PlanState::ExecProcNode, HashJoin::hashclauses, HashJoin::hashcollations, HashJoin::hashkeys, HashJoin::hashoperators, 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, makeNode, outerPlan, outerPlanState, Join::plan, PlanState::plan, JoinState::ps, HashState::ps, PlanState::ps_ResultTupleSlot, Plan::qual, PlanState::qual, JoinState::single_match, PlanState::state, and TTSOpsVirtual.

Referenced by ExecInitNode().

599 {
600  HashJoinState *hjstate;
601  Plan *outerNode;
602  Hash *hashNode;
603  TupleDesc outerDesc,
604  innerDesc;
605  const TupleTableSlotOps *ops;
606 
607  /* check for unsupported flags */
608  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
609 
610  /*
611  * create state structure
612  */
613  hjstate = makeNode(HashJoinState);
614  hjstate->js.ps.plan = (Plan *) node;
615  hjstate->js.ps.state = estate;
616 
617  /*
618  * See ExecHashJoinInitializeDSM() and ExecHashJoinInitializeWorker()
619  * where this function may be replaced with a parallel version, if we
620  * managed to launch a parallel query.
621  */
622  hjstate->js.ps.ExecProcNode = ExecHashJoin;
623  hjstate->js.jointype = node->join.jointype;
624 
625  /*
626  * Miscellaneous initialization
627  *
628  * create expression context for node
629  */
630  ExecAssignExprContext(estate, &hjstate->js.ps);
631 
632  /*
633  * initialize child nodes
634  *
635  * Note: we could suppress the REWIND flag for the inner input, which
636  * would amount to betting that the hash will be a single batch. Not
637  * clear if this would be a win or not.
638  */
639  outerNode = outerPlan(node);
640  hashNode = (Hash *) innerPlan(node);
641 
642  outerPlanState(hjstate) = ExecInitNode(outerNode, estate, eflags);
643  outerDesc = ExecGetResultType(outerPlanState(hjstate));
644  innerPlanState(hjstate) = ExecInitNode((Plan *) hashNode, estate, eflags);
645  innerDesc = ExecGetResultType(innerPlanState(hjstate));
646 
647  /*
648  * Initialize result slot, type and projection.
649  */
651  ExecAssignProjectionInfo(&hjstate->js.ps, NULL);
652 
653  /*
654  * tuple table initialization
655  */
656  ops = ExecGetResultSlotOps(outerPlanState(hjstate), NULL);
657  hjstate->hj_OuterTupleSlot = ExecInitExtraTupleSlot(estate, outerDesc,
658  ops);
659 
660  /*
661  * detect whether we need only consider the first matching inner tuple
662  */
663  hjstate->js.single_match = (node->join.inner_unique ||
664  node->join.jointype == JOIN_SEMI);
665 
666  /* set up null tuples for outer joins, if needed */
667  switch (node->join.jointype)
668  {
669  case JOIN_INNER:
670  case JOIN_SEMI:
671  break;
672  case JOIN_LEFT:
673  case JOIN_ANTI:
674  hjstate->hj_NullInnerTupleSlot =
675  ExecInitNullTupleSlot(estate, innerDesc, &TTSOpsVirtual);
676  break;
677  case JOIN_RIGHT:
678  hjstate->hj_NullOuterTupleSlot =
679  ExecInitNullTupleSlot(estate, outerDesc, &TTSOpsVirtual);
680  break;
681  case JOIN_FULL:
682  hjstate->hj_NullOuterTupleSlot =
683  ExecInitNullTupleSlot(estate, outerDesc, &TTSOpsVirtual);
684  hjstate->hj_NullInnerTupleSlot =
685  ExecInitNullTupleSlot(estate, innerDesc, &TTSOpsVirtual);
686  break;
687  default:
688  elog(ERROR, "unrecognized join type: %d",
689  (int) node->join.jointype);
690  }
691 
692  /*
693  * now for some voodoo. our temporary tuple slot is actually the result
694  * tuple slot of the Hash node (which is our inner plan). we can do this
695  * because Hash nodes don't return tuples via ExecProcNode() -- instead
696  * the hash join node uses ExecScanHashBucket() to get at the contents of
697  * the hash table. -cim 6/9/91
698  */
699  {
700  HashState *hashstate = (HashState *) innerPlanState(hjstate);
701  TupleTableSlot *slot = hashstate->ps.ps_ResultTupleSlot;
702 
703  hjstate->hj_HashTupleSlot = slot;
704  }
705 
706  /*
707  * initialize child expressions
708  */
709  hjstate->js.ps.qual =
710  ExecInitQual(node->join.plan.qual, (PlanState *) hjstate);
711  hjstate->js.joinqual =
712  ExecInitQual(node->join.joinqual, (PlanState *) hjstate);
713  hjstate->hashclauses =
714  ExecInitQual(node->hashclauses, (PlanState *) hjstate);
715 
716  /*
717  * initialize hash-specific info
718  */
719  hjstate->hj_HashTable = NULL;
720  hjstate->hj_FirstOuterTupleSlot = NULL;
721 
722  hjstate->hj_CurHashValue = 0;
723  hjstate->hj_CurBucketNo = 0;
725  hjstate->hj_CurTuple = NULL;
726 
727  hjstate->hj_OuterHashKeys = ExecInitExprList(node->hashkeys,
728  (PlanState *) hjstate);
729  hjstate->hj_HashOperators = node->hashoperators;
730  hjstate->hj_Collations = node->hashcollations;
731 
732  hjstate->hj_JoinState = HJ_BUILD_HASHTABLE;
733  hjstate->hj_MatchedOuter = false;
734  hjstate->hj_OuterNotEmpty = false;
735 
736  return hjstate;
737 }
JoinType jointype
Definition: execnodes.h:1831
List * qual
Definition: plannodes.h:141
#define INVALID_SKEW_BUCKET_NO
Definition: hashjoin.h:109
TupleTableSlot * hj_NullInnerTupleSlot
Definition: execnodes.h:1945
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1801
ExprState * joinqual
Definition: execnodes.h:1834
const TupleTableSlotOps * ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
Definition: execUtils.c:463
List * hashkeys
Definition: plannodes.h:747
PlanState ps
Definition: execnodes.h:1830
List * hashclauses
Definition: plannodes.h:739
bool single_match
Definition: execnodes.h:1832
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
bool hj_MatchedOuter
Definition: execnodes.h:1948
EState * state
Definition: execnodes.h:941
TupleTableSlot * hj_OuterTupleSlot
Definition: execnodes.h:1942
List * hj_OuterHashKeys
Definition: execnodes.h:1934
TupleTableSlot * hj_FirstOuterTupleSlot
Definition: execnodes.h:1946
Join join
Definition: plannodes.h:738
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:207
List * hashcollations
Definition: plannodes.h:741
JoinType jointype
Definition: plannodes.h:680
uint32 hj_CurHashValue
Definition: execnodes.h:1938
int hj_CurSkewBucketNo
Definition: execnodes.h:1940
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:977
#define ERROR
Definition: elog.h:43
TupleTableSlot * hj_NullOuterTupleSlot
Definition: execnodes.h:1944
List * hashoperators
Definition: plannodes.h:740
#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
HashJoinTuple hj_CurTuple
Definition: execnodes.h:1941
List * ExecInitExprList(List *nodes, PlanState *parent)
Definition: execExpr.c:316
PlanState ps
Definition: execnodes.h:2270
List * hj_HashOperators
Definition: execnodes.h:1935
#define outerPlan(node)
Definition: plannodes.h:170
int hj_CurBucketNo
Definition: execnodes.h:1939
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:945
List * hj_Collations
Definition: execnodes.h:1936
Plan * plan
Definition: execnodes.h:939
#define makeNode(_type_)
Definition: nodes.h:573
bool hj_OuterNotEmpty
Definition: execnodes.h:1949
#define Assert(condition)
Definition: c.h:739
#define EXEC_FLAG_MARK
Definition: executor.h:59
TupleTableSlot * ExecInitNullTupleSlot(EState *estate, TupleDesc tupType, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1817
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:444
void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1769
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:454
ExprState * qual
Definition: execnodes.h:960
TupleTableSlot * hj_HashTupleSlot
Definition: execnodes.h:1943
#define HJ_BUILD_HASHTABLE
Definition: nodeHashjoin.c:124
HashJoinTable hj_HashTable
Definition: execnodes.h:1937
#define elog(elevel,...)
Definition: elog.h:228
static TupleTableSlot * ExecHashJoin(PlanState *pstate)
Definition: nodeHashjoin.c:566
bool inner_unique
Definition: plannodes.h:681
#define innerPlanState(node)
Definition: execnodes.h:1032
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:138
JoinState js
Definition: execnodes.h:1932
List * joinqual
Definition: plannodes.h:682
ExprState * hashclauses
Definition: execnodes.h:1933
Plan plan
Definition: plannodes.h:679

◆ ExecReScanHashJoin()

void ExecReScanHashJoin ( HashJoinState node)

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

1281 {
1282  /*
1283  * In a multi-batch join, we currently have to do rescans the hard way,
1284  * primarily because batch temp files may have already been released. But
1285  * if it's a single-batch join, and there is no parameter change for the
1286  * inner subnode, then we can just re-use the existing hash table without
1287  * rebuilding it.
1288  */
1289  if (node->hj_HashTable != NULL)
1290  {
1291  if (node->hj_HashTable->nbatch == 1 &&
1292  node->js.ps.righttree->chgParam == NULL)
1293  {
1294  /*
1295  * Okay to reuse the hash table; needn't rescan inner, either.
1296  *
1297  * However, if it's a right/full join, we'd better reset the
1298  * inner-tuple match flags contained in the table.
1299  */
1300  if (HJ_FILL_INNER(node))
1302 
1303  /*
1304  * Also, we need to reset our state about the emptiness of the
1305  * outer relation, so that the new scan of the outer will update
1306  * it correctly if it turns out to be empty this time. (There's no
1307  * harm in clearing it now because ExecHashJoin won't need the
1308  * info. In the other cases, where the hash table doesn't exist
1309  * or we are destroying it, we leave this state alone because
1310  * ExecHashJoin will need it the first time through.)
1311  */
1312  node->hj_OuterNotEmpty = false;
1313 
1314  /* ExecHashJoin can skip the BUILD_HASHTABLE step */
1316  }
1317  else
1318  {
1319  /* must destroy and rebuild hash table */
1321  node->hj_HashTable = NULL;
1323 
1324  /*
1325  * if chgParam of subnode is not null then plan will be re-scanned
1326  * by first ExecProcNode.
1327  */
1328  if (node->js.ps.righttree->chgParam == NULL)
1329  ExecReScan(node->js.ps.righttree);
1330  }
1331  }
1332 
1333  /* Always reset intra-tuple state */
1334  node->hj_CurHashValue = 0;
1335  node->hj_CurBucketNo = 0;
1337  node->hj_CurTuple = NULL;
1338 
1339  node->hj_MatchedOuter = false;
1340  node->hj_FirstOuterTupleSlot = NULL;
1341 
1342  /*
1343  * if chgParam of subnode is not null then plan will be re-scanned by
1344  * first ExecProcNode.
1345  */
1346  if (node->js.ps.lefttree->chgParam == NULL)
1347  ExecReScan(node->js.ps.lefttree);
1348 }
#define INVALID_SKEW_BUCKET_NO
Definition: hashjoin.h:109
PlanState ps
Definition: execnodes.h:1830
void ExecReScan(PlanState *node)
Definition: execAmi.c:75
bool hj_MatchedOuter
Definition: execnodes.h:1948
struct PlanState * righttree
Definition: execnodes.h:962
TupleTableSlot * hj_FirstOuterTupleSlot
Definition: execnodes.h:1946
struct PlanState * lefttree
Definition: execnodes.h:961
#define HJ_FILL_INNER(hjstate)
Definition: nodeHashjoin.c:134
uint32 hj_CurHashValue
Definition: execnodes.h:1938
int hj_CurSkewBucketNo
Definition: execnodes.h:1940
HashJoinTuple hj_CurTuple
Definition: execnodes.h:1941
Bitmapset * chgParam
Definition: execnodes.h:971
int hj_CurBucketNo
Definition: execnodes.h:1939
bool hj_OuterNotEmpty
Definition: execnodes.h:1949
#define HJ_NEED_NEW_OUTER
Definition: nodeHashjoin.c:125
#define HJ_BUILD_HASHTABLE
Definition: nodeHashjoin.c:124
HashJoinTable hj_HashTable
Definition: execnodes.h:1937
void ExecHashTableResetMatchFlags(HashJoinTable hashtable)
Definition: nodeHash.c:2163
JoinState js
Definition: execnodes.h:1932
void ExecHashTableDestroy(HashJoinTable hashtable)
Definition: nodeHash.c:853

◆ ExecShutdownHashJoin()

void ExecShutdownHashJoin ( HashJoinState node)

Definition at line 1351 of file nodeHashjoin.c.

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

Referenced by ExecShutdownNode().

1352 {
1353  if (node->hj_HashTable)
1354  {
1355  /*
1356  * Detach from shared state before DSM memory goes away. This makes
1357  * sure that we don't have any pointers into DSM memory by the time
1358  * ExecEndHashJoin runs.
1359  */
1362  }
1363 }
void ExecHashTableDetachBatch(HashJoinTable hashtable)
Definition: nodeHash.c:3084
void ExecHashTableDetach(HashJoinTable hashtable)
Definition: nodeHash.c:3141
HashJoinTable hj_HashTable
Definition: execnodes.h:1937