aboutsummaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
Diffstat (limited to 'src/include')
-rw-r--r--src/include/access/htup.h23
-rw-r--r--src/include/executor/hashjoin.h2
-rw-r--r--src/include/executor/nodeHash.h10
-rw-r--r--src/include/nodes/execnodes.h23
4 files changed, 45 insertions, 13 deletions
diff --git a/src/include/access/htup.h b/src/include/access/htup.h
index adf1321052c..f540966d684 100644
--- a/src/include/access/htup.h
+++ b/src/include/access/htup.h
@@ -196,6 +196,14 @@ typedef HeapTupleHeaderData *HeapTupleHeader;
#define HEAP2_XACT_MASK 0xC000 /* visibility-related bits */
/*
+ * HEAP_TUPLE_HAS_MATCH is a temporary flag used during hash joins. It is
+ * only used in tuples that are in the hash table, and those don't need
+ * any visibility information, so we can overlay it on a visibility flag
+ * instead of using up a dedicated bit.
+ */
+#define HEAP_TUPLE_HAS_MATCH HEAP_ONLY_TUPLE /* tuple has a join match */
+
+/*
* HeapTupleHeader accessor macros
*
* Note: beware of multiple evaluations of "tup" argument. But the Set
@@ -343,6 +351,21 @@ do { \
(tup)->t_infomask2 &= ~HEAP_ONLY_TUPLE \
)
+#define HeapTupleHeaderHasMatch(tup) \
+( \
+ (tup)->t_infomask2 & HEAP_TUPLE_HAS_MATCH \
+)
+
+#define HeapTupleHeaderSetMatch(tup) \
+( \
+ (tup)->t_infomask2 |= HEAP_TUPLE_HAS_MATCH \
+)
+
+#define HeapTupleHeaderClearMatch(tup) \
+( \
+ (tup)->t_infomask2 &= ~HEAP_TUPLE_HAS_MATCH \
+)
+
#define HeapTupleHeaderGetNatts(tup) \
((tup)->t_infomask2 & HEAP_NATTS_MASK)
diff --git a/src/include/executor/hashjoin.h b/src/include/executor/hashjoin.h
index 1b93f58af67..c4aa0d37268 100644
--- a/src/include/executor/hashjoin.h
+++ b/src/include/executor/hashjoin.h
@@ -113,6 +113,8 @@ typedef struct HashJoinTableData
struct HashJoinTupleData **buckets;
/* buckets array is per-batch storage, as are all the tuples */
+ bool keepNulls; /* true to store unmatchable NULL tuples */
+
bool skewEnabled; /* are we using skew optimization? */
HashSkewBucket **skewBucket; /* hashtable of skew buckets */
int skewBucketLen; /* size of skewBucket array (a power of 2!) */
diff --git a/src/include/executor/nodeHash.h b/src/include/executor/nodeHash.h
index 444a0137a2d..8517d1cf284 100644
--- a/src/include/executor/nodeHash.h
+++ b/src/include/executor/nodeHash.h
@@ -22,7 +22,8 @@ extern Node *MultiExecHash(HashState *node);
extern void ExecEndHash(HashState *node);
extern void ExecReScanHash(HashState *node);
-extern HashJoinTable ExecHashTableCreate(Hash *node, List *hashOperators);
+extern HashJoinTable ExecHashTableCreate(Hash *node, List *hashOperators,
+ bool keepNulls);
extern void ExecHashTableDestroy(HashJoinTable hashtable);
extern void ExecHashTableInsert(HashJoinTable hashtable,
TupleTableSlot *slot,
@@ -37,9 +38,12 @@ extern void ExecHashGetBucketAndBatch(HashJoinTable hashtable,
uint32 hashvalue,
int *bucketno,
int *batchno);
-extern HashJoinTuple ExecScanHashBucket(HashJoinState *hjstate,
- ExprContext *econtext);
+extern bool ExecScanHashBucket(HashJoinState *hjstate, ExprContext *econtext);
+extern void ExecPrepHashTableForUnmatched(HashJoinState *hjstate);
+extern bool ExecScanHashTableForUnmatched(HashJoinState *hjstate,
+ ExprContext *econtext);
extern void ExecHashTableReset(HashJoinTable hashtable);
+extern void ExecHashTableResetMatchFlags(HashJoinTable hashtable);
extern void ExecChooseHashTableSize(double ntuples, int tupwidth, bool useskew,
int *numbuckets,
int *numbatches,
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index d669c24b981..6af4bb8d76c 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1468,6 +1468,10 @@ typedef struct MergeJoinState
/* ----------------
* HashJoinState information
*
+ * hashclauses original form of the hashjoin condition
+ * hj_OuterHashKeys the outer hash keys in the hashjoin condition
+ * hj_InnerHashKeys the inner hash keys in the hashjoin condition
+ * hj_HashOperators the join operators in the hashjoin condition
* hj_HashTable hash table for the hashjoin
* (NULL if table not built yet)
* hj_CurHashValue hash value for current outer tuple
@@ -1477,14 +1481,12 @@ typedef struct MergeJoinState
* tuple, or NULL if starting search
* (hj_CurXXX variables are undefined if
* OuterTupleSlot is empty!)
- * hj_OuterHashKeys the outer hash keys in the hashjoin condition
- * hj_InnerHashKeys the inner hash keys in the hashjoin condition
- * hj_HashOperators the join operators in the hashjoin condition
* hj_OuterTupleSlot tuple slot for outer tuples
- * hj_HashTupleSlot tuple slot for hashed tuples
- * hj_NullInnerTupleSlot prepared null tuple for left outer joins
+ * hj_HashTupleSlot tuple slot for inner (hashed) tuples
+ * hj_NullOuterTupleSlot prepared null tuple for right/full outer joins
+ * hj_NullInnerTupleSlot prepared null tuple for left/full outer joins
* hj_FirstOuterTupleSlot first tuple retrieved from outer plan
- * hj_NeedNewOuter true if need new outer tuple on next call
+ * hj_JoinState current state of ExecHashJoin state machine
* hj_MatchedOuter true if found a join match for current outer
* hj_OuterNotEmpty true if outer relation known not empty
* ----------------
@@ -1498,19 +1500,20 @@ typedef struct HashJoinState
{
JoinState js; /* its first field is NodeTag */
List *hashclauses; /* list of ExprState nodes */
+ List *hj_OuterHashKeys; /* list of ExprState nodes */
+ List *hj_InnerHashKeys; /* list of ExprState nodes */
+ List *hj_HashOperators; /* list of operator OIDs */
HashJoinTable hj_HashTable;
uint32 hj_CurHashValue;
int hj_CurBucketNo;
int hj_CurSkewBucketNo;
HashJoinTuple hj_CurTuple;
- List *hj_OuterHashKeys; /* list of ExprState nodes */
- List *hj_InnerHashKeys; /* list of ExprState nodes */
- List *hj_HashOperators; /* list of operator OIDs */
TupleTableSlot *hj_OuterTupleSlot;
TupleTableSlot *hj_HashTupleSlot;
+ TupleTableSlot *hj_NullOuterTupleSlot;
TupleTableSlot *hj_NullInnerTupleSlot;
TupleTableSlot *hj_FirstOuterTupleSlot;
- bool hj_NeedNewOuter;
+ int hj_JoinState;
bool hj_MatchedOuter;
bool hj_OuterNotEmpty;
} HashJoinState;