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, HashJoinTable hashtable)
 

Function Documentation

◆ ExecEndHashJoin()

void ExecEndHashJoin ( HashJoinState node)

Definition at line 858 of file nodeHashjoin.c.

859 {
860  /*
861  * Free hash table
862  */
863  if (node->hj_HashTable)
864  {
866  node->hj_HashTable = NULL;
867  }
868 
869  /*
870  * clean up subtrees
871  */
874 }
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:557
#define outerPlanState(node)
Definition: execnodes.h:1213
#define innerPlanState(node)
Definition: execnodes.h:1212
void ExecHashTableDestroy(HashJoinTable hashtable)
Definition: nodeHash.c:883
HashJoinTable hj_HashTable
Definition: execnodes.h:2194

References ExecEndNode(), ExecHashTableDestroy(), HashJoinState::hj_HashTable, innerPlanState, and outerPlanState.

Referenced by ExecEndNode().

◆ ExecHashJoinEstimate()

void ExecHashJoinEstimate ( HashJoinState state,
ParallelContext pcxt 
)

Definition at line 1543 of file nodeHashjoin.c.

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

References ParallelContext::estimator, shm_toc_estimate_chunk, and shm_toc_estimate_keys.

Referenced by ExecParallelEstimate().

◆ ExecHashJoinInitializeDSM()

void ExecHashJoinInitializeDSM ( HashJoinState state,
ParallelContext pcxt 
)

Definition at line 1550 of file nodeHashjoin.c.

1551 {
1552  int plan_node_id = state->js.ps.plan->plan_node_id;
1553  HashState *hashNode;
1554  ParallelHashJoinState *pstate;
1555 
1556  /*
1557  * Disable shared hash table mode if we failed to create a real DSM
1558  * segment, because that means that we don't have a DSA area to work with.
1559  */
1560  if (pcxt->seg == NULL)
1561  return;
1562 
1564 
1565  /*
1566  * Set up the state needed to coordinate access to the shared hash
1567  * table(s), using the plan node ID as the toc key.
1568  */
1569  pstate = shm_toc_allocate(pcxt->toc, sizeof(ParallelHashJoinState));
1570  shm_toc_insert(pcxt->toc, plan_node_id, pstate);
1571 
1572  /*
1573  * Set up the shared hash join state with no batches initially.
1574  * ExecHashTableCreate() will prepare at least one later and set nbatch
1575  * and space_allowed.
1576  */
1577  pstate->nbatch = 0;
1578  pstate->space_allowed = 0;
1579  pstate->batches = InvalidDsaPointer;
1580  pstate->old_batches = InvalidDsaPointer;
1581  pstate->nbuckets = 0;
1582  pstate->growth = PHJ_GROWTH_OK;
1584  pg_atomic_init_u32(&pstate->distributor, 0);
1585  pstate->nparticipants = pcxt->nworkers + 1;
1586  pstate->total_tuples = 0;
1587  LWLockInitialize(&pstate->lock,
1589  BarrierInit(&pstate->build_barrier, 0);
1590  BarrierInit(&pstate->grow_batches_barrier, 0);
1591  BarrierInit(&pstate->grow_buckets_barrier, 0);
1592 
1593  /* Set up the space we'll use for shared temporary files. */
1594  SharedFileSetInit(&pstate->fileset, pcxt->seg);
1595 
1596  /* Initialize the shared state in the hash node. */
1597  hashNode = (HashState *) innerPlanState(state);
1598  hashNode->parallel_state = pstate;
1599 }
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:216
void BarrierInit(Barrier *barrier, int participants)
Definition: barrier.c:100
#define InvalidDsaPointer
Definition: dsa.h:78
void ExecSetExecProcNode(PlanState *node, ExecProcNodeMtd function)
Definition: execProcnode.c:425
@ PHJ_GROWTH_OK
Definition: hashjoin.h:233
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:709
@ LWTRANCHE_PARALLEL_HASH_JOIN
Definition: lwlock.h:194
static TupleTableSlot * ExecParallelHashJoin(PlanState *pstate)
Definition: nodeHashjoin.c:693
void SharedFileSetInit(SharedFileSet *fileset, dsm_segment *seg)
Definition: sharedfileset.c:38
void shm_toc_insert(shm_toc *toc, uint64 key, void *address)
Definition: shm_toc.c:171
void * shm_toc_allocate(shm_toc *toc, Size nbytes)
Definition: shm_toc.c:88
struct ParallelHashJoinState * parallel_state
Definition: execnodes.h:2764
dsm_segment * seg
Definition: parallel.h:42
shm_toc * toc
Definition: parallel.h:44
Barrier grow_batches_barrier
Definition: hashjoin.h:261
dsa_pointer old_batches
Definition: hashjoin.h:249
dsa_pointer chunk_work_queue
Definition: hashjoin.h:254
Barrier grow_buckets_barrier
Definition: hashjoin.h:262
ParallelHashGrowth growth
Definition: hashjoin.h:253
pg_atomic_uint32 distributor
Definition: hashjoin.h:263
SharedFileSet fileset
Definition: hashjoin.h:265
dsa_pointer batches
Definition: hashjoin.h:248
Definition: regguts.h:323

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, 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, ParallelContext::seg, SharedFileSetInit(), shm_toc_allocate(), shm_toc_insert(), ParallelHashJoinState::space_allowed, ParallelContext::toc, and ParallelHashJoinState::total_tuples.

Referenced by ExecParallelInitializeDSM().

◆ ExecHashJoinInitializeWorker()

void ExecHashJoinInitializeWorker ( HashJoinState state,
ParallelWorkerContext pwcxt 
)

Definition at line 1641 of file nodeHashjoin.c.

1643 {
1644  HashState *hashNode;
1645  int plan_node_id = state->js.ps.plan->plan_node_id;
1646  ParallelHashJoinState *pstate =
1647  shm_toc_lookup(pwcxt->toc, plan_node_id, false);
1648 
1649  /* Attach to the space for shared temporary files. */
1650  SharedFileSetAttach(&pstate->fileset, pwcxt->seg);
1651 
1652  /* Attach to the shared state in the hash node. */
1653  hashNode = (HashState *) innerPlanState(state);
1654  hashNode->parallel_state = pstate;
1655 
1657 }
void SharedFileSetAttach(SharedFileSet *fileset, dsm_segment *seg)
Definition: sharedfileset.c:56
void * shm_toc_lookup(shm_toc *toc, uint64 key, bool noError)
Definition: shm_toc.c:232
dsm_segment * seg
Definition: parallel.h:52

References ExecParallelHashJoin(), ExecSetExecProcNode(), ParallelHashJoinState::fileset, innerPlanState, HashState::parallel_state, ParallelWorkerContext::seg, SharedFileSetAttach(), shm_toc_lookup(), and ParallelWorkerContext::toc.

Referenced by ExecParallelInitializeWorker().

◆ ExecHashJoinReInitializeDSM()

void ExecHashJoinReInitializeDSM ( HashJoinState state,
ParallelContext pcxt 
)

Definition at line 1608 of file nodeHashjoin.c.

1609 {
1610  int plan_node_id = state->js.ps.plan->plan_node_id;
1611  ParallelHashJoinState *pstate =
1612  shm_toc_lookup(pcxt->toc, plan_node_id, false);
1613 
1614  /*
1615  * It would be possible to reuse the shared hash table in single-batch
1616  * cases by resetting and then fast-forwarding build_barrier to
1617  * PHJ_BUILD_FREE and batch 0's batch_barrier to PHJ_BATCH_PROBE, but
1618  * currently shared hash tables are already freed by now (by the last
1619  * participant to detach from the batch). We could consider keeping it
1620  * around for single-batch joins. We'd also need to adjust
1621  * finalize_plan() so that it doesn't record a dummy dependency for
1622  * Parallel Hash nodes, preventing the rescan optimization. For now we
1623  * don't try.
1624  */
1625 
1626  /* Detach, freeing any remaining shared memory. */
1627  if (state->hj_HashTable != NULL)
1628  {
1629  ExecHashTableDetachBatch(state->hj_HashTable);
1630  ExecHashTableDetach(state->hj_HashTable);
1631  }
1632 
1633  /* Clear any shared batch files. */
1634  SharedFileSetDeleteAll(&pstate->fileset);
1635 
1636  /* Reset build_barrier to PHJ_BUILD_ELECT so we can go around again. */
1637  BarrierInit(&pstate->build_barrier, 0);
1638 }
void ExecHashTableDetachBatch(HashJoinTable hashtable)
Definition: nodeHash.c:3282
void ExecHashTableDetach(HashJoinTable hashtable)
Definition: nodeHash.c:3374
void SharedFileSetDeleteAll(SharedFileSet *fileset)
Definition: sharedfileset.c:83

References BarrierInit(), ParallelHashJoinState::build_barrier, ExecHashTableDetach(), ExecHashTableDetachBatch(), ParallelHashJoinState::fileset, SharedFileSetDeleteAll(), shm_toc_lookup(), and ParallelContext::toc.

Referenced by ExecParallelReInitializeDSM().

◆ ExecHashJoinSaveTuple()

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

Definition at line 1314 of file nodeHashjoin.c.

1316 {
1317  BufFile *file = *fileptr;
1318 
1319  /*
1320  * The batch file is lazily created. If this is the first tuple written to
1321  * this batch, the batch file is created and its buffer is allocated in
1322  * the spillCxt context, NOT in the batchCxt.
1323  *
1324  * During the build phase, buffered files are created for inner batches.
1325  * Each batch's buffered file is closed (and its buffer freed) after the
1326  * batch is loaded into memory during the outer side scan. Therefore, it
1327  * is necessary to allocate the batch file buffer in a memory context
1328  * which outlives the batch itself.
1329  *
1330  * Also, we use spillCxt instead of hashCxt for a better accounting of the
1331  * spilling memory consumption.
1332  */
1333  if (file == NULL)
1334  {
1335  MemoryContext oldctx = MemoryContextSwitchTo(hashtable->spillCxt);
1336 
1337  file = BufFileCreateTemp(false);
1338  *fileptr = file;
1339 
1340  MemoryContextSwitchTo(oldctx);
1341  }
1342 
1343  BufFileWrite(file, &hashvalue, sizeof(uint32));
1344  BufFileWrite(file, tuple, tuple->t_len);
1345 }
BufFile * BufFileCreateTemp(bool interXact)
Definition: buffile.c:193
void BufFileWrite(BufFile *file, const void *ptr, size_t size)
Definition: buffile.c:676
unsigned int uint32
Definition: c.h:506
MemoryContextSwitchTo(old_ctx)
MemoryContext spillCxt
Definition: hashjoin.h:364

References BufFileCreateTemp(), BufFileWrite(), MemoryContextSwitchTo(), HashJoinTableData::spillCxt, and MinimalTupleData::t_len.

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

◆ ExecInitHashJoin()

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

Definition at line 709 of file nodeHashjoin.c.

710 {
711  HashJoinState *hjstate;
712  Plan *outerNode;
713  Hash *hashNode;
714  TupleDesc outerDesc,
715  innerDesc;
716  const TupleTableSlotOps *ops;
717 
718  /* check for unsupported flags */
719  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
720 
721  /*
722  * create state structure
723  */
724  hjstate = makeNode(HashJoinState);
725  hjstate->js.ps.plan = (Plan *) node;
726  hjstate->js.ps.state = estate;
727 
728  /*
729  * See ExecHashJoinInitializeDSM() and ExecHashJoinInitializeWorker()
730  * where this function may be replaced with a parallel version, if we
731  * managed to launch a parallel query.
732  */
733  hjstate->js.ps.ExecProcNode = ExecHashJoin;
734  hjstate->js.jointype = node->join.jointype;
735 
736  /*
737  * Miscellaneous initialization
738  *
739  * create expression context for node
740  */
741  ExecAssignExprContext(estate, &hjstate->js.ps);
742 
743  /*
744  * initialize child nodes
745  *
746  * Note: we could suppress the REWIND flag for the inner input, which
747  * would amount to betting that the hash will be a single batch. Not
748  * clear if this would be a win or not.
749  */
750  outerNode = outerPlan(node);
751  hashNode = (Hash *) innerPlan(node);
752 
753  outerPlanState(hjstate) = ExecInitNode(outerNode, estate, eflags);
754  outerDesc = ExecGetResultType(outerPlanState(hjstate));
755  innerPlanState(hjstate) = ExecInitNode((Plan *) hashNode, estate, eflags);
756  innerDesc = ExecGetResultType(innerPlanState(hjstate));
757 
758  /*
759  * Initialize result slot, type and projection.
760  */
762  ExecAssignProjectionInfo(&hjstate->js.ps, NULL);
763 
764  /*
765  * tuple table initialization
766  */
767  ops = ExecGetResultSlotOps(outerPlanState(hjstate), NULL);
768  hjstate->hj_OuterTupleSlot = ExecInitExtraTupleSlot(estate, outerDesc,
769  ops);
770 
771  /*
772  * detect whether we need only consider the first matching inner tuple
773  */
774  hjstate->js.single_match = (node->join.inner_unique ||
775  node->join.jointype == JOIN_SEMI);
776 
777  /* set up null tuples for outer joins, if needed */
778  switch (node->join.jointype)
779  {
780  case JOIN_INNER:
781  case JOIN_SEMI:
782  break;
783  case JOIN_LEFT:
784  case JOIN_ANTI:
785  hjstate->hj_NullInnerTupleSlot =
786  ExecInitNullTupleSlot(estate, innerDesc, &TTSOpsVirtual);
787  break;
788  case JOIN_RIGHT:
789  case JOIN_RIGHT_ANTI:
790  hjstate->hj_NullOuterTupleSlot =
791  ExecInitNullTupleSlot(estate, outerDesc, &TTSOpsVirtual);
792  break;
793  case JOIN_FULL:
794  hjstate->hj_NullOuterTupleSlot =
795  ExecInitNullTupleSlot(estate, outerDesc, &TTSOpsVirtual);
796  hjstate->hj_NullInnerTupleSlot =
797  ExecInitNullTupleSlot(estate, innerDesc, &TTSOpsVirtual);
798  break;
799  default:
800  elog(ERROR, "unrecognized join type: %d",
801  (int) node->join.jointype);
802  }
803 
804  /*
805  * now for some voodoo. our temporary tuple slot is actually the result
806  * tuple slot of the Hash node (which is our inner plan). we can do this
807  * because Hash nodes don't return tuples via ExecProcNode() -- instead
808  * the hash join node uses ExecScanHashBucket() to get at the contents of
809  * the hash table. -cim 6/9/91
810  */
811  {
812  HashState *hashstate = (HashState *) innerPlanState(hjstate);
813  TupleTableSlot *slot = hashstate->ps.ps_ResultTupleSlot;
814 
815  hjstate->hj_HashTupleSlot = slot;
816  }
817 
818  /*
819  * initialize child expressions
820  */
821  hjstate->js.ps.qual =
822  ExecInitQual(node->join.plan.qual, (PlanState *) hjstate);
823  hjstate->js.joinqual =
824  ExecInitQual(node->join.joinqual, (PlanState *) hjstate);
825  hjstate->hashclauses =
826  ExecInitQual(node->hashclauses, (PlanState *) hjstate);
827 
828  /*
829  * initialize hash-specific info
830  */
831  hjstate->hj_HashTable = NULL;
832  hjstate->hj_FirstOuterTupleSlot = NULL;
833 
834  hjstate->hj_CurHashValue = 0;
835  hjstate->hj_CurBucketNo = 0;
837  hjstate->hj_CurTuple = NULL;
838 
839  hjstate->hj_OuterHashKeys = ExecInitExprList(node->hashkeys,
840  (PlanState *) hjstate);
841  hjstate->hj_HashOperators = node->hashoperators;
842  hjstate->hj_Collations = node->hashcollations;
843 
844  hjstate->hj_JoinState = HJ_BUILD_HASHTABLE;
845  hjstate->hj_MatchedOuter = false;
846  hjstate->hj_OuterNotEmpty = false;
847 
848  return hjstate;
849 }
#define Assert(condition)
Definition: c.h:858
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
List * ExecInitExprList(List *nodes, PlanState *parent)
Definition: execExpr.c:326
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
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_MARK
Definition: executor.h:69
#define INVALID_SKEW_BUCKET_NO
Definition: hashjoin.h:120
static TupleTableSlot * ExecHashJoin(PlanState *pstate)
Definition: nodeHashjoin.c:677
#define HJ_BUILD_HASHTABLE
Definition: nodeHashjoin.c:179
#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:309
@ JOIN_ANTI
Definition: nodes.h:308
#define innerPlan(node)
Definition: plannodes.h:181
#define outerPlan(node)
Definition: plannodes.h:182
HashJoinTuple hj_CurTuple
Definition: execnodes.h:2198
int hj_CurSkewBucketNo
Definition: execnodes.h:2197
List * hj_OuterHashKeys
Definition: execnodes.h:2191
TupleTableSlot * hj_NullOuterTupleSlot
Definition: execnodes.h:2201
TupleTableSlot * hj_OuterTupleSlot
Definition: execnodes.h:2199
bool hj_OuterNotEmpty
Definition: execnodes.h:2206
TupleTableSlot * hj_NullInnerTupleSlot
Definition: execnodes.h:2202
List * hj_HashOperators
Definition: execnodes.h:2192
ExprState * hashclauses
Definition: execnodes.h:2190
JoinState js
Definition: execnodes.h:2189
TupleTableSlot * hj_FirstOuterTupleSlot
Definition: execnodes.h:2203
bool hj_MatchedOuter
Definition: execnodes.h:2205
uint32 hj_CurHashValue
Definition: execnodes.h:2195
List * hj_Collations
Definition: execnodes.h:2193
int hj_CurBucketNo
Definition: execnodes.h:2196
TupleTableSlot * hj_HashTupleSlot
Definition: execnodes.h:2200
List * hashcollations
Definition: plannodes.h:867
List * hashclauses
Definition: plannodes.h:865
List * hashoperators
Definition: plannodes.h:866
Join join
Definition: plannodes.h:864
List * hashkeys
Definition: plannodes.h:873
PlanState ps
Definition: execnodes.h:2744
JoinType jointype
Definition: execnodes.h:2087
PlanState ps
Definition: execnodes.h:2086
ExprState * joinqual
Definition: execnodes.h:2090
bool single_match
Definition: execnodes.h:2088
List * joinqual
Definition: plannodes.h:793
JoinType jointype
Definition: plannodes.h:791
bool inner_unique
Definition: plannodes.h:792
ExprState * qual
Definition: execnodes.h:1138
Plan * plan
Definition: execnodes.h:1117
EState * state
Definition: execnodes.h:1119
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1155
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:1123

References Assert, elog, ERROR, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, ExecAssignExprContext(), ExecAssignProjectionInfo(), ExecGetResultSlotOps(), ExecGetResultType(), ExecHashJoin(), ExecInitExprList(), ExecInitExtraTupleSlot(), ExecInitNode(), ExecInitNullTupleSlot(), ExecInitQual(), ExecInitResultTupleSlotTL(), PlanState::ExecProcNode, HashJoinState::hashclauses, HashJoin::hashclauses, HashJoin::hashcollations, HashJoin::hashkeys, HashJoin::hashoperators, HJ_BUILD_HASHTABLE, HashJoinState::hj_Collations, HashJoinState::hj_CurBucketNo, HashJoinState::hj_CurHashValue, HashJoinState::hj_CurSkewBucketNo, HashJoinState::hj_CurTuple, HashJoinState::hj_FirstOuterTupleSlot, HashJoinState::hj_HashOperators, HashJoinState::hj_HashTable, HashJoinState::hj_HashTupleSlot, HashJoinState::hj_JoinState, HashJoinState::hj_MatchedOuter, HashJoinState::hj_NullInnerTupleSlot, HashJoinState::hj_NullOuterTupleSlot, HashJoinState::hj_OuterHashKeys, HashJoinState::hj_OuterNotEmpty, 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_RIGHT_ANTI, JOIN_SEMI, JoinState::joinqual, Join::joinqual, JoinState::jointype, Join::jointype, HashJoinState::js, makeNode, outerPlan, outerPlanState, PlanState::plan, JoinState::ps, HashState::ps, PlanState::ps_ResultTupleSlot, PlanState::qual, JoinState::single_match, PlanState::state, and TTSOpsVirtual.

Referenced by ExecInitNode().

◆ ExecReScanHashJoin()

void ExecReScanHashJoin ( HashJoinState node)

Definition at line 1394 of file nodeHashjoin.c.

1395 {
1398 
1399  /*
1400  * In a multi-batch join, we currently have to do rescans the hard way,
1401  * primarily because batch temp files may have already been released. But
1402  * if it's a single-batch join, and there is no parameter change for the
1403  * inner subnode, then we can just re-use the existing hash table without
1404  * rebuilding it.
1405  */
1406  if (node->hj_HashTable != NULL)
1407  {
1408  if (node->hj_HashTable->nbatch == 1 &&
1409  innerPlan->chgParam == NULL)
1410  {
1411  /*
1412  * Okay to reuse the hash table; needn't rescan inner, either.
1413  *
1414  * However, if it's a right/right-anti/full join, we'd better
1415  * reset the inner-tuple match flags contained in the table.
1416  */
1417  if (HJ_FILL_INNER(node))
1419 
1420  /*
1421  * Also, we need to reset our state about the emptiness of the
1422  * outer relation, so that the new scan of the outer will update
1423  * it correctly if it turns out to be empty this time. (There's no
1424  * harm in clearing it now because ExecHashJoin won't need the
1425  * info. In the other cases, where the hash table doesn't exist
1426  * or we are destroying it, we leave this state alone because
1427  * ExecHashJoin will need it the first time through.)
1428  */
1429  node->hj_OuterNotEmpty = false;
1430 
1431  /* ExecHashJoin can skip the BUILD_HASHTABLE step */
1433  }
1434  else
1435  {
1436  /* must destroy and rebuild hash table */
1437  HashState *hashNode = castNode(HashState, innerPlan);
1438 
1439  Assert(hashNode->hashtable == node->hj_HashTable);
1440  /* accumulate stats from old hash table, if wanted */
1441  /* (this should match ExecShutdownHash) */
1442  if (hashNode->ps.instrument && !hashNode->hinstrument)
1443  hashNode->hinstrument = (HashInstrumentation *)
1444  palloc0(sizeof(HashInstrumentation));
1445  if (hashNode->hinstrument)
1447  hashNode->hashtable);
1448  /* for safety, be sure to clear child plan node's pointer too */
1449  hashNode->hashtable = NULL;
1450 
1452  node->hj_HashTable = NULL;
1454 
1455  /*
1456  * if chgParam of subnode is not null then plan will be re-scanned
1457  * by first ExecProcNode.
1458  */
1459  if (innerPlan->chgParam == NULL)
1461  }
1462  }
1463 
1464  /* Always reset intra-tuple state */
1465  node->hj_CurHashValue = 0;
1466  node->hj_CurBucketNo = 0;
1468  node->hj_CurTuple = NULL;
1469 
1470  node->hj_MatchedOuter = false;
1471  node->hj_FirstOuterTupleSlot = NULL;
1472 
1473  /*
1474  * if chgParam of subnode is not null then plan will be re-scanned by
1475  * first ExecProcNode.
1476  */
1477  if (outerPlan->chgParam == NULL)
1479 }
void ExecReScan(PlanState *node)
Definition: execAmi.c:76
void * palloc0(Size size)
Definition: mcxt.c:1346
void ExecHashAccumInstrumentation(HashInstrumentation *instrument, HashJoinTable hashtable)
Definition: nodeHash.c:2850
void ExecHashTableResetMatchFlags(HashJoinTable hashtable)
Definition: nodeHash.c:2327
#define HJ_FILL_INNER(hjstate)
Definition: nodeHashjoin.c:189
#define HJ_NEED_NEW_OUTER
Definition: nodeHashjoin.c:180
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
HashJoinTable hashtable
Definition: execnodes.h:2745
HashInstrumentation * hinstrument
Definition: execnodes.h:2761
Instrumentation * instrument
Definition: execnodes.h:1127

References Assert, castNode, ExecHashAccumInstrumentation(), ExecHashTableDestroy(), ExecHashTableResetMatchFlags(), ExecReScan(), HashState::hashtable, HashState::hinstrument, 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, innerPlan, innerPlanState, PlanState::instrument, INVALID_SKEW_BUCKET_NO, HashJoinTableData::nbatch, outerPlan, outerPlanState, palloc0(), and HashState::ps.

Referenced by ExecReScan().

◆ ExecShutdownHashJoin()

void ExecShutdownHashJoin ( HashJoinState node)

Definition at line 1482 of file nodeHashjoin.c.

1483 {
1484  if (node->hj_HashTable)
1485  {
1486  /*
1487  * Detach from shared state before DSM memory goes away. This makes
1488  * sure that we don't have any pointers into DSM memory by the time
1489  * ExecEndHashJoin runs.
1490  */
1493  }
1494 }

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

Referenced by ExecShutdownNode_walker().