PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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:1222
#define innerPlanState(node)
Definition: execnodes.h:1221
void ExecHashTableDestroy(HashJoinTable hashtable)
Definition: nodeHash.c:866
HashJoinTable hj_HashTable
Definition: execnodes.h:2225

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

Referenced by ExecEndNode().

◆ ExecHashJoinEstimate()

void ExecHashJoinEstimate ( HashJoinState state,
ParallelContext pcxt 
)

Definition at line 1649 of file nodeHashjoin.c.

1650{
1653}
#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 1656 of file nodeHashjoin.c.

1657{
1658 int plan_node_id = state->js.ps.plan->plan_node_id;
1659 HashState *hashNode;
1660 ParallelHashJoinState *pstate;
1661
1662 /*
1663 * Disable shared hash table mode if we failed to create a real DSM
1664 * segment, because that means that we don't have a DSA area to work with.
1665 */
1666 if (pcxt->seg == NULL)
1667 return;
1668
1670
1671 /*
1672 * Set up the state needed to coordinate access to the shared hash
1673 * table(s), using the plan node ID as the toc key.
1674 */
1675 pstate = shm_toc_allocate(pcxt->toc, sizeof(ParallelHashJoinState));
1676 shm_toc_insert(pcxt->toc, plan_node_id, pstate);
1677
1678 /*
1679 * Set up the shared hash join state with no batches initially.
1680 * ExecHashTableCreate() will prepare at least one later and set nbatch
1681 * and space_allowed.
1682 */
1683 pstate->nbatch = 0;
1684 pstate->space_allowed = 0;
1685 pstate->batches = InvalidDsaPointer;
1687 pstate->nbuckets = 0;
1688 pstate->growth = PHJ_GROWTH_OK;
1690 pg_atomic_init_u32(&pstate->distributor, 0);
1691 pstate->nparticipants = pcxt->nworkers + 1;
1692 pstate->total_tuples = 0;
1693 LWLockInitialize(&pstate->lock,
1695 BarrierInit(&pstate->build_barrier, 0);
1696 BarrierInit(&pstate->grow_batches_barrier, 0);
1697 BarrierInit(&pstate->grow_buckets_barrier, 0);
1698
1699 /* Set up the space we'll use for shared temporary files. */
1700 SharedFileSetInit(&pstate->fileset, pcxt->seg);
1701
1702 /* Initialize the shared state in the hash node. */
1703 hashNode = (HashState *) innerPlanState(state);
1704 hashNode->parallel_state = pstate;
1705}
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_allocate(shm_toc *toc, Size nbytes)
Definition: shm_toc.c:88
void shm_toc_insert(shm_toc *toc, uint64 key, void *address)
Definition: shm_toc.c:171
struct ParallelHashJoinState * parallel_state
Definition: execnodes.h:2800
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 1752 of file nodeHashjoin.c.

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

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

References BarrierInit(), ParallelHashJoinState::build_barrier, ExecHashTableDetach(), ExecHashTableDetachBatch(), ParallelHashJoinState::fileset, ParallelContext::seg, 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
uint32_t uint32
Definition: c.h:485
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
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 */
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
935 hjstate->hj_MatchedOuter = false;
936 hjstate->hj_OuterNotEmpty = false;
937
938 return hjstate;
939}
#define Assert(condition)
Definition: c.h:812
#define OidIsValid(objectId)
Definition: c.h:729
#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:4156
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:142
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:84
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:2018
void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1986
TupleTableSlot * ExecInitNullTupleSlot(EState *estate, TupleDesc tupType, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:2034
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:495
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:485
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition: execUtils.c:583
const TupleTableSlotOps * ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
Definition: execUtils.c:504
#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:76
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:72
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:2229
int hj_CurSkewBucketNo
Definition: execnodes.h:2228
ExprState * hj_OuterHash
Definition: execnodes.h:2224
TupleTableSlot * hj_NullOuterTupleSlot
Definition: execnodes.h:2232
TupleTableSlot * hj_OuterTupleSlot
Definition: execnodes.h:2230
bool hj_OuterNotEmpty
Definition: execnodes.h:2237
TupleTableSlot * hj_NullInnerTupleSlot
Definition: execnodes.h:2233
ExprState * hashclauses
Definition: execnodes.h:2223
JoinState js
Definition: execnodes.h:2222
TupleTableSlot * hj_FirstOuterTupleSlot
Definition: execnodes.h:2234
bool hj_MatchedOuter
Definition: execnodes.h:2236
uint32 hj_CurHashValue
Definition: execnodes.h:2226
int hj_CurBucketNo
Definition: execnodes.h:2227
TupleTableSlot * hj_HashTupleSlot
Definition: execnodes.h:2231
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:2779
Oid skew_collation
Definition: execnodes.h:2782
FmgrInfo * skew_hashfunction
Definition: execnodes.h:2781
PlanState ps
Definition: execnodes.h:2777
JoinType jointype
Definition: execnodes.h:2121
PlanState ps
Definition: execnodes.h:2120
ExprState * joinqual
Definition: execnodes.h:2124
bool single_match
Definition: execnodes.h:2122
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:1203
ExprState * qual
Definition: execnodes.h:1147
Plan * plan
Definition: execnodes.h:1126
EState * state
Definition: execnodes.h:1128
TupleDesc ps_ResultTupleDesc
Definition: execnodes.h:1163
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1164
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:1132

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/right-semi/full join, we'd
1515 * better reset the inner-tuple match flags contained in the
1516 * table.
1517 */
1518 if (HJ_FILL_INNER(node) || node->js.jointype == JOIN_RIGHT_SEMI)
1520
1521 /*
1522 * Also, we need to reset our state about the emptiness of the
1523 * outer relation, so that the new scan of the outer will update
1524 * it correctly if it turns out to be empty this time. (There's no
1525 * harm in clearing it now because ExecHashJoin won't need the
1526 * info. In the other cases, where the hash table doesn't exist
1527 * or we are destroying it, we leave this state alone because
1528 * ExecHashJoin will need it the first time through.)
1529 */
1530 node->hj_OuterNotEmpty = false;
1531
1532 /* ExecHashJoin can skip the BUILD_HASHTABLE step */
1534 }
1535 else
1536 {
1537 /* must destroy and rebuild hash table */
1538 HashState *hashNode = castNode(HashState, innerPlan);
1539
1540 Assert(hashNode->hashtable == node->hj_HashTable);
1541 /* accumulate stats from old hash table, if wanted */
1542 /* (this should match ExecShutdownHash) */
1543 if (hashNode->ps.instrument && !hashNode->hinstrument)
1544 hashNode->hinstrument = (HashInstrumentation *)
1546 if (hashNode->hinstrument)
1548 hashNode->hashtable);
1549 /* for safety, be sure to clear child plan node's pointer too */
1550 hashNode->hashtable = NULL;
1551
1553 node->hj_HashTable = NULL;
1555
1556 /*
1557 * if chgParam of subnode is not null then plan will be re-scanned
1558 * by first ExecProcNode.
1559 */
1560 if (innerPlan->chgParam == NULL)
1562 }
1563 }
1564
1565 /* Always reset intra-tuple state */
1566 node->hj_CurHashValue = 0;
1567 node->hj_CurBucketNo = 0;
1569 node->hj_CurTuple = NULL;
1570
1571 node->hj_MatchedOuter = false;
1572 node->hj_FirstOuterTupleSlot = NULL;
1573
1574 /*
1575 * if chgParam of subnode is not null then plan will be re-scanned by
1576 * first ExecProcNode.
1577 */
1578 if (outerPlan->chgParam == NULL)
1580}
void ExecReScan(PlanState *node)
Definition: execAmi.c:76
void ExecHashAccumInstrumentation(HashInstrumentation *instrument, HashJoinTable hashtable)
Definition: nodeHash.c:2742
void ExecHashTableResetMatchFlags(HashJoinTable hashtable)
Definition: nodeHash.c:2220
#define HJ_NEED_NEW_OUTER
Definition: nodeHashjoin.c:181
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
HashJoinTable hashtable
Definition: execnodes.h:2778
HashInstrumentation * hinstrument
Definition: execnodes.h:2797
Instrumentation * instrument
Definition: execnodes.h:1136

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, JOIN_RIGHT_SEMI, JoinState::jointype, HashJoinState::js, HashJoinTableData::nbatch, outerPlan, outerPlanState, palloc0(), and HashState::ps.

Referenced by ExecReScan().

◆ ExecShutdownHashJoin()

void ExecShutdownHashJoin ( HashJoinState node)

Definition at line 1583 of file nodeHashjoin.c.

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

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

Referenced by ExecShutdownNode_walker().