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 948 of file nodeHashjoin.c.

949 {
950  /*
951  * Free hash table
952  */
953  if (node->hj_HashTable)
954  {
956  node->hj_HashTable = NULL;
957  }
958 
959  /*
960  * clean up subtrees
961  */
964 }
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:562
#define outerPlanState(node)
Definition: execnodes.h:1216
#define innerPlanState(node)
Definition: execnodes.h:1215
void ExecHashTableDestroy(HashJoinTable hashtable)
Definition: nodeHash.c:867
HashJoinTable hj_HashTable
Definition: execnodes.h:2221

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

Referenced by ExecEndNode().

◆ ExecHashJoinEstimate()

void ExecHashJoinEstimate ( HashJoinState state,
ParallelContext pcxt 
)

Definition at line 1648 of file nodeHashjoin.c.

1649 {
1651  shm_toc_estimate_keys(&pcxt->estimator, 1);
1652 }
#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 1655 of file nodeHashjoin.c.

1656 {
1657  int plan_node_id = state->js.ps.plan->plan_node_id;
1658  HashState *hashNode;
1659  ParallelHashJoinState *pstate;
1660 
1661  /*
1662  * Disable shared hash table mode if we failed to create a real DSM
1663  * segment, because that means that we don't have a DSA area to work with.
1664  */
1665  if (pcxt->seg == NULL)
1666  return;
1667 
1669 
1670  /*
1671  * Set up the state needed to coordinate access to the shared hash
1672  * table(s), using the plan node ID as the toc key.
1673  */
1674  pstate = shm_toc_allocate(pcxt->toc, sizeof(ParallelHashJoinState));
1675  shm_toc_insert(pcxt->toc, plan_node_id, pstate);
1676 
1677  /*
1678  * Set up the shared hash join state with no batches initially.
1679  * ExecHashTableCreate() will prepare at least one later and set nbatch
1680  * and space_allowed.
1681  */
1682  pstate->nbatch = 0;
1683  pstate->space_allowed = 0;
1684  pstate->batches = InvalidDsaPointer;
1685  pstate->old_batches = InvalidDsaPointer;
1686  pstate->nbuckets = 0;
1687  pstate->growth = PHJ_GROWTH_OK;
1689  pg_atomic_init_u32(&pstate->distributor, 0);
1690  pstate->nparticipants = pcxt->nworkers + 1;
1691  pstate->total_tuples = 0;
1692  LWLockInitialize(&pstate->lock,
1694  BarrierInit(&pstate->build_barrier, 0);
1695  BarrierInit(&pstate->grow_batches_barrier, 0);
1696  BarrierInit(&pstate->grow_buckets_barrier, 0);
1697 
1698  /* Set up the space we'll use for shared temporary files. */
1699  SharedFileSetInit(&pstate->fileset, pcxt->seg);
1700 
1701  /* Initialize the shared state in the hash node. */
1702  hashNode = (HashState *) innerPlanState(state);
1703  hashNode->parallel_state = pstate;
1704 }
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:221
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:430
@ PHJ_GROWTH_OK
Definition: hashjoin.h:233
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:707
@ LWTRANCHE_PARALLEL_HASH_JOIN
Definition: lwlock.h:194
static TupleTableSlot * ExecParallelHashJoin(PlanState *pstate)
Definition: nodeHashjoin.c:700
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:2796
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 1746 of file nodeHashjoin.c.

1748 {
1749  HashState *hashNode;
1750  int plan_node_id = state->js.ps.plan->plan_node_id;
1751  ParallelHashJoinState *pstate =
1752  shm_toc_lookup(pwcxt->toc, plan_node_id, false);
1753 
1754  /* Attach to the space for shared temporary files. */
1755  SharedFileSetAttach(&pstate->fileset, pwcxt->seg);
1756 
1757  /* Attach to the shared state in the hash node. */
1758  hashNode = (HashState *) innerPlanState(state);
1759  hashNode->parallel_state = pstate;
1760 
1762 }
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 1713 of file nodeHashjoin.c.

1714 {
1715  int plan_node_id = state->js.ps.plan->plan_node_id;
1716  ParallelHashJoinState *pstate =
1717  shm_toc_lookup(pcxt->toc, plan_node_id, false);
1718 
1719  /*
1720  * It would be possible to reuse the shared hash table in single-batch
1721  * cases by resetting and then fast-forwarding build_barrier to
1722  * PHJ_BUILD_FREE and batch 0's batch_barrier to PHJ_BATCH_PROBE, but
1723  * currently shared hash tables are already freed by now (by the last
1724  * participant to detach from the batch). We could consider keeping it
1725  * around for single-batch joins. We'd also need to adjust
1726  * finalize_plan() so that it doesn't record a dummy dependency for
1727  * Parallel Hash nodes, preventing the rescan optimization. For now we
1728  * don't try.
1729  */
1730 
1731  /* Detach, freeing any remaining shared memory. */
1732  if (state->hj_HashTable != NULL)
1733  {
1734  ExecHashTableDetachBatch(state->hj_HashTable);
1735  ExecHashTableDetach(state->hj_HashTable);
1736  }
1737 
1738  /* Clear any shared batch files. */
1739  SharedFileSetDeleteAll(&pstate->fileset);
1740 
1741  /* Reset build_barrier to PHJ_BUILD_ELECT so we can go around again. */
1742  BarrierInit(&pstate->build_barrier, 0);
1743 }
void ExecHashTableDetachBatch(HashJoinTable hashtable)
Definition: nodeHash.c:3168
void ExecHashTableDetach(HashJoinTable hashtable)
Definition: nodeHash.c:3260
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 1414 of file nodeHashjoin.c.

1416 {
1417  BufFile *file = *fileptr;
1418 
1419  /*
1420  * The batch file is lazily created. If this is the first tuple written to
1421  * this batch, the batch file is created and its buffer is allocated in
1422  * the spillCxt context, NOT in the batchCxt.
1423  *
1424  * During the build phase, buffered files are created for inner batches.
1425  * Each batch's buffered file is closed (and its buffer freed) after the
1426  * batch is loaded into memory during the outer side scan. Therefore, it
1427  * is necessary to allocate the batch file buffer in a memory context
1428  * which outlives the batch itself.
1429  *
1430  * Also, we use spillCxt instead of hashCxt for a better accounting of the
1431  * spilling memory consumption.
1432  */
1433  if (file == NULL)
1434  {
1435  MemoryContext oldctx = MemoryContextSwitchTo(hashtable->spillCxt);
1436 
1437  file = BufFileCreateTemp(false);
1438  *fileptr = file;
1439 
1440  MemoryContextSwitchTo(oldctx);
1441  }
1442 
1443  BufFileWrite(file, &hashvalue, sizeof(uint32));
1444  BufFileWrite(file, tuple, tuple->t_len);
1445 }
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:352

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 716 of file nodeHashjoin.c.

717 {
718  HashJoinState *hjstate;
719  Plan *outerNode;
720  Hash *hashNode;
721  TupleDesc outerDesc,
722  innerDesc;
723  const TupleTableSlotOps *ops;
724 
725  /* check for unsupported flags */
726  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
727 
728  /*
729  * create state structure
730  */
731  hjstate = makeNode(HashJoinState);
732  hjstate->js.ps.plan = (Plan *) node;
733  hjstate->js.ps.state = estate;
734 
735  /*
736  * See ExecHashJoinInitializeDSM() and ExecHashJoinInitializeWorker()
737  * where this function may be replaced with a parallel version, if we
738  * managed to launch a parallel query.
739  */
740  hjstate->js.ps.ExecProcNode = ExecHashJoin;
741  hjstate->js.jointype = node->join.jointype;
742 
743  /*
744  * Miscellaneous initialization
745  *
746  * create expression context for node
747  */
748  ExecAssignExprContext(estate, &hjstate->js.ps);
749 
750  /*
751  * initialize child nodes
752  *
753  * Note: we could suppress the REWIND flag for the inner input, which
754  * would amount to betting that the hash will be a single batch. Not
755  * clear if this would be a win or not.
756  */
757  outerNode = outerPlan(node);
758  hashNode = (Hash *) innerPlan(node);
759 
760  outerPlanState(hjstate) = ExecInitNode(outerNode, estate, eflags);
761  outerDesc = ExecGetResultType(outerPlanState(hjstate));
762  innerPlanState(hjstate) = ExecInitNode((Plan *) hashNode, estate, eflags);
763  innerDesc = ExecGetResultType(innerPlanState(hjstate));
764 
765  /*
766  * Initialize result slot, type and projection.
767  */
769  ExecAssignProjectionInfo(&hjstate->js.ps, NULL);
770 
771  /*
772  * tuple table initialization
773  */
774  ops = ExecGetResultSlotOps(outerPlanState(hjstate), NULL);
775  hjstate->hj_OuterTupleSlot = ExecInitExtraTupleSlot(estate, outerDesc,
776  ops);
777 
778  /*
779  * detect whether we need only consider the first matching inner tuple
780  */
781  hjstate->js.single_match = (node->join.inner_unique ||
782  node->join.jointype == JOIN_SEMI);
783 
784  /* set up null tuples for outer joins, if needed */
785  switch (node->join.jointype)
786  {
787  case JOIN_INNER:
788  case JOIN_SEMI:
789  case JOIN_RIGHT_SEMI:
790  break;
791  case JOIN_LEFT:
792  case JOIN_ANTI:
793  hjstate->hj_NullInnerTupleSlot =
794  ExecInitNullTupleSlot(estate, innerDesc, &TTSOpsVirtual);
795  break;
796  case JOIN_RIGHT:
797  case JOIN_RIGHT_ANTI:
798  hjstate->hj_NullOuterTupleSlot =
799  ExecInitNullTupleSlot(estate, outerDesc, &TTSOpsVirtual);
800  break;
801  case JOIN_FULL:
802  hjstate->hj_NullOuterTupleSlot =
803  ExecInitNullTupleSlot(estate, outerDesc, &TTSOpsVirtual);
804  hjstate->hj_NullInnerTupleSlot =
805  ExecInitNullTupleSlot(estate, innerDesc, &TTSOpsVirtual);
806  break;
807  default:
808  elog(ERROR, "unrecognized join type: %d",
809  (int) node->join.jointype);
810  }
811 
812  /*
813  * now for some voodoo. our temporary tuple slot is actually the result
814  * tuple slot of the Hash node (which is our inner plan). we can do this
815  * because Hash nodes don't return tuples via ExecProcNode() -- instead
816  * the hash join node uses ExecScanHashBucket() to get at the contents of
817  * the hash table. -cim 6/9/91
818  */
819  {
820  HashState *hashstate = (HashState *) innerPlanState(hjstate);
821  Hash *hash = (Hash *) hashstate->ps.plan;
822  TupleTableSlot *slot = hashstate->ps.ps_ResultTupleSlot;
823  Oid *outer_hashfuncid;
824  Oid *inner_hashfuncid;
825  bool *hash_strict;
826  ListCell *lc;
827  int nkeys;
828 
829 
830  hjstate->hj_HashTupleSlot = slot;
831 
832  /*
833  * Build ExprStates to obtain hash values for either side of the join.
834  * This must be done here as ExecBuildHash32Expr needs to know how to
835  * handle NULL inputs and the required handling of that depends on the
836  * jointype. We don't know the join type in ExecInitHash() and we
837  * must build the ExprStates before ExecHashTableCreate() so we
838  * properly attribute any SubPlans that exist in the hash expressions
839  * to the correct PlanState.
840  */
841  nkeys = list_length(node->hashoperators);
842 
843  outer_hashfuncid = palloc_array(Oid, nkeys);
844  inner_hashfuncid = palloc_array(Oid, nkeys);
845  hash_strict = palloc_array(bool, nkeys);
846 
847  /*
848  * Determine the hash function for each side of the join for the given
849  * hash operator.
850  */
851  foreach(lc, node->hashoperators)
852  {
853  Oid hashop = lfirst_oid(lc);
854  int i = foreach_current_index(lc);
855 
856  if (!get_op_hash_functions(hashop,
857  &outer_hashfuncid[i],
858  &inner_hashfuncid[i]))
859  elog(ERROR,
860  "could not find hash function for hash operator %u",
861  hashop);
862  hash_strict[i] = op_strict(hashop);
863  }
864 
865  /*
866  * Build an ExprState to generate the hash value for the expressions
867  * on the outer of the join. This ExprState must finish generating
868  * the hash value when HJ_FILL_OUTER() is true. Otherwise,
869  * ExecBuildHash32Expr will set up the ExprState to abort early if it
870  * finds a NULL. In these cases, we don't need to store these tuples
871  * in the hash table as the jointype does not require it.
872  */
873  hjstate->hj_OuterHash =
875  hjstate->js.ps.resultops,
876  outer_hashfuncid,
877  node->hashcollations,
878  node->hashkeys,
879  hash_strict,
880  &hjstate->js.ps,
881  0,
882  HJ_FILL_OUTER(hjstate));
883 
884  /* As above, but for the inner side of the join */
885  hashstate->hash_expr =
887  hashstate->ps.resultops,
888  inner_hashfuncid,
889  node->hashcollations,
890  hash->hashkeys,
891  hash_strict,
892  &hashstate->ps,
893  0,
894  HJ_FILL_INNER(hjstate));
895 
896  /*
897  * Set up the skew table hash function while we have a record of the
898  * first key's hash function Oid.
899  */
900  if (OidIsValid(hash->skewTable))
901  {
902  hashstate->skew_hashfunction = palloc0(sizeof(FmgrInfo));
903  hashstate->skew_collation = linitial_oid(node->hashcollations);
904  fmgr_info(outer_hashfuncid[0], hashstate->skew_hashfunction);
905  }
906 
907  /* no need to keep these */
908  pfree(outer_hashfuncid);
909  pfree(inner_hashfuncid);
910  pfree(hash_strict);
911  }
912 
913  /*
914  * initialize child expressions
915  */
916  hjstate->js.ps.qual =
917  ExecInitQual(node->join.plan.qual, (PlanState *) hjstate);
918  hjstate->js.joinqual =
919  ExecInitQual(node->join.joinqual, (PlanState *) hjstate);
920  hjstate->hashclauses =
921  ExecInitQual(node->hashclauses, (PlanState *) hjstate);
922 
923  /*
924  * initialize hash-specific info
925  */
926  hjstate->hj_HashTable = NULL;
927  hjstate->hj_FirstOuterTupleSlot = NULL;
928 
929  hjstate->hj_CurHashValue = 0;
930  hjstate->hj_CurBucketNo = 0;
932  hjstate->hj_CurTuple = NULL;
933 
934  hjstate->hj_JoinState = HJ_BUILD_HASHTABLE;
935  hjstate->hj_MatchedOuter = false;
936  hjstate->hj_OuterNotEmpty = false;
937 
938  return hjstate;
939 }
#define Assert(condition)
Definition: c.h:858
#define OidIsValid(objectId)
Definition: c.h:775
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:224
ExprState * ExecBuildHash32Expr(TupleDesc desc, const TupleTableSlotOps *ops, const Oid *hashfunc_oids, const List *collations, const List *hash_exprs, const bool *opstrict, PlanState *parent, uint32 init_value, bool keep_nulls)
Definition: execExpr.c:3992
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 palloc_array(type, count)
Definition: fe_memutils.h:64
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:127
#define INVALID_SKEW_BUCKET_NO
Definition: hashjoin.h:120
int i
Definition: isn.c:73
bool op_strict(Oid opno)
Definition: lsyscache.c:1477
bool get_op_hash_functions(Oid opno, RegProcedure *lhs_procno, RegProcedure *rhs_procno)
Definition: lsyscache.c:510
void pfree(void *pointer)
Definition: mcxt.c:1521
void * palloc0(Size size)
Definition: mcxt.c:1347
#define HJ_FILL_INNER(hjstate)
Definition: nodeHashjoin.c:190
#define HJ_FILL_OUTER(hjstate)
Definition: nodeHashjoin.c:188
static TupleTableSlot * ExecHashJoin(PlanState *pstate)
Definition: nodeHashjoin.c:684
#define HJ_BUILD_HASHTABLE
Definition: nodeHashjoin.c:180
#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_RIGHT_SEMI
Definition: nodes.h:309
@ JOIN_LEFT
Definition: nodes.h:294
@ JOIN_RIGHT_ANTI
Definition: nodes.h:310
@ JOIN_ANTI
Definition: nodes.h:308
static int list_length(const List *l)
Definition: pg_list.h:152
#define foreach_current_index(var_or_cell)
Definition: pg_list.h:403
#define linitial_oid(l)
Definition: pg_list.h:180
#define lfirst_oid(lc)
Definition: pg_list.h:174
#define innerPlan(node)
Definition: plannodes.h:182
#define outerPlan(node)
Definition: plannodes.h:183
unsigned int Oid
Definition: postgres_ext.h:31
static unsigned hash(unsigned *uv, int n)
Definition: rege_dfa.c:715
Definition: fmgr.h:57
HashJoinTuple hj_CurTuple
Definition: execnodes.h:2225
int hj_CurSkewBucketNo
Definition: execnodes.h:2224
ExprState * hj_OuterHash
Definition: execnodes.h:2220
TupleTableSlot * hj_NullOuterTupleSlot
Definition: execnodes.h:2228
TupleTableSlot * hj_OuterTupleSlot
Definition: execnodes.h:2226
bool hj_OuterNotEmpty
Definition: execnodes.h:2233
TupleTableSlot * hj_NullInnerTupleSlot
Definition: execnodes.h:2229
ExprState * hashclauses
Definition: execnodes.h:2219
JoinState js
Definition: execnodes.h:2218
TupleTableSlot * hj_FirstOuterTupleSlot
Definition: execnodes.h:2230
bool hj_MatchedOuter
Definition: execnodes.h:2232
uint32 hj_CurHashValue
Definition: execnodes.h:2222
int hj_CurBucketNo
Definition: execnodes.h:2223
TupleTableSlot * hj_HashTupleSlot
Definition: execnodes.h:2227
List * hashcollations
Definition: plannodes.h:868
List * hashclauses
Definition: plannodes.h:866
List * hashoperators
Definition: plannodes.h:867
Join join
Definition: plannodes.h:865
List * hashkeys
Definition: plannodes.h:874
ExprState * hash_expr
Definition: execnodes.h:2775
Oid skew_collation
Definition: execnodes.h:2778
FmgrInfo * skew_hashfunction
Definition: execnodes.h:2777
PlanState ps
Definition: execnodes.h:2773
JoinType jointype
Definition: execnodes.h:2117
PlanState ps
Definition: execnodes.h:2116
ExprState * joinqual
Definition: execnodes.h:2120
bool single_match
Definition: execnodes.h:2118
List * joinqual
Definition: plannodes.h:794
JoinType jointype
Definition: plannodes.h:792
bool inner_unique
Definition: plannodes.h:793
const TupleTableSlotOps * resultops
Definition: execnodes.h:1197
ExprState * qual
Definition: execnodes.h:1141
Plan * plan
Definition: execnodes.h:1120
EState * state
Definition: execnodes.h:1122
TupleDesc ps_ResultTupleDesc
Definition: execnodes.h:1157
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1158
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:1126

References Assert, elog, ERROR, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, ExecAssignExprContext(), ExecAssignProjectionInfo(), ExecBuildHash32Expr(), ExecGetResultSlotOps(), ExecGetResultType(), ExecHashJoin(), ExecInitExtraTupleSlot(), ExecInitNode(), ExecInitNullTupleSlot(), ExecInitQual(), ExecInitResultTupleSlotTL(), PlanState::ExecProcNode, fmgr_info(), foreach_current_index, get_op_hash_functions(), hash(), HashState::hash_expr, HashJoinState::hashclauses, HashJoin::hashclauses, HashJoin::hashcollations, HashJoin::hashkeys, HashJoin::hashoperators, HJ_BUILD_HASHTABLE, HashJoinState::hj_CurBucketNo, HashJoinState::hj_CurHashValue, HashJoinState::hj_CurSkewBucketNo, HashJoinState::hj_CurTuple, HJ_FILL_INNER, HJ_FILL_OUTER, HashJoinState::hj_FirstOuterTupleSlot, HashJoinState::hj_HashTable, HashJoinState::hj_HashTupleSlot, HashJoinState::hj_JoinState, HashJoinState::hj_MatchedOuter, HashJoinState::hj_NullInnerTupleSlot, HashJoinState::hj_NullOuterTupleSlot, HashJoinState::hj_OuterHash, HashJoinState::hj_OuterNotEmpty, HashJoinState::hj_OuterTupleSlot, i, 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_RIGHT_SEMI, JOIN_SEMI, JoinState::joinqual, Join::joinqual, JoinState::jointype, Join::jointype, HashJoinState::js, lfirst_oid, linitial_oid, list_length(), makeNode, OidIsValid, op_strict(), outerPlan, outerPlanState, palloc0(), palloc_array, pfree(), PlanState::plan, JoinState::ps, HashState::ps, PlanState::ps_ResultTupleDesc, PlanState::ps_ResultTupleSlot, PlanState::qual, PlanState::resultops, JoinState::single_match, HashState::skew_collation, HashState::skew_hashfunction, PlanState::state, and TTSOpsVirtual.

Referenced by ExecInitNode().

◆ ExecReScanHashJoin()

void ExecReScanHashJoin ( HashJoinState node)

Definition at line 1494 of file nodeHashjoin.c.

1495 {
1498 
1499  /*
1500  * In a multi-batch join, we currently have to do rescans the hard way,
1501  * primarily because batch temp files may have already been released. But
1502  * if it's a single-batch join, and there is no parameter change for the
1503  * inner subnode, then we can just re-use the existing hash table without
1504  * rebuilding it.
1505  */
1506  if (node->hj_HashTable != NULL)
1507  {
1508  if (node->hj_HashTable->nbatch == 1 &&
1509  innerPlan->chgParam == NULL)
1510  {
1511  /*
1512  * Okay to reuse the hash table; needn't rescan inner, either.
1513  *
1514  * However, if it's a right/right-anti/full join, we'd better
1515  * reset the inner-tuple match flags contained in the table.
1516  */
1517  if (HJ_FILL_INNER(node))
1519 
1520  /*
1521  * Also, we need to reset our state about the emptiness of the
1522  * outer relation, so that the new scan of the outer will update
1523  * it correctly if it turns out to be empty this time. (There's no
1524  * harm in clearing it now because ExecHashJoin won't need the
1525  * info. In the other cases, where the hash table doesn't exist
1526  * or we are destroying it, we leave this state alone because
1527  * ExecHashJoin will need it the first time through.)
1528  */
1529  node->hj_OuterNotEmpty = false;
1530 
1531  /* ExecHashJoin can skip the BUILD_HASHTABLE step */
1533  }
1534  else
1535  {
1536  /* must destroy and rebuild hash table */
1537  HashState *hashNode = castNode(HashState, innerPlan);
1538 
1539  Assert(hashNode->hashtable == node->hj_HashTable);
1540  /* accumulate stats from old hash table, if wanted */
1541  /* (this should match ExecShutdownHash) */
1542  if (hashNode->ps.instrument && !hashNode->hinstrument)
1543  hashNode->hinstrument = (HashInstrumentation *)
1544  palloc0(sizeof(HashInstrumentation));
1545  if (hashNode->hinstrument)
1547  hashNode->hashtable);
1548  /* for safety, be sure to clear child plan node's pointer too */
1549  hashNode->hashtable = NULL;
1550 
1552  node->hj_HashTable = NULL;
1554 
1555  /*
1556  * if chgParam of subnode is not null then plan will be re-scanned
1557  * by first ExecProcNode.
1558  */
1559  if (innerPlan->chgParam == NULL)
1561  }
1562  }
1563 
1564  /* Always reset intra-tuple state */
1565  node->hj_CurHashValue = 0;
1566  node->hj_CurBucketNo = 0;
1568  node->hj_CurTuple = NULL;
1569 
1570  node->hj_MatchedOuter = false;
1571  node->hj_FirstOuterTupleSlot = NULL;
1572 
1573  /*
1574  * if chgParam of subnode is not null then plan will be re-scanned by
1575  * first ExecProcNode.
1576  */
1577  if (outerPlan->chgParam == NULL)
1579 }
void ExecReScan(PlanState *node)
Definition: execAmi.c:76
void ExecHashAccumInstrumentation(HashInstrumentation *instrument, HashJoinTable hashtable)
Definition: nodeHash.c:2736
void ExecHashTableResetMatchFlags(HashJoinTable hashtable)
Definition: nodeHash.c:2214
#define HJ_NEED_NEW_OUTER
Definition: nodeHashjoin.c:181
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
HashJoinTable hashtable
Definition: execnodes.h:2774
HashInstrumentation * hinstrument
Definition: execnodes.h:2793
Instrumentation * instrument
Definition: execnodes.h:1130

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 1582 of file nodeHashjoin.c.

1583 {
1584  if (node->hj_HashTable)
1585  {
1586  /*
1587  * Detach from shared state before DSM memory goes away. This makes
1588  * sure that we don't have any pointers into DSM memory by the time
1589  * ExecEndHashJoin runs.
1590  */
1593  }
1594 }

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

Referenced by ExecShutdownNode_walker().