aboutsummaryrefslogtreecommitdiff
path: root/src/include/executor
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2010-12-30 20:24:55 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2010-12-30 20:26:08 -0500
commitf4e4b3274317d9ce30de7e7e5b04dece7c4e1791 (patch)
tree6e3b700d25cb841749b4313e69bb4c30583e666c /src/include/executor
parent17cb9e8c984746d3bbdf0d94367a0c5a6e2b6aee (diff)
downloadpostgresql-f4e4b3274317d9ce30de7e7e5b04dece7c4e1791.tar.gz
postgresql-f4e4b3274317d9ce30de7e7e5b04dece7c4e1791.zip
Support RIGHT and FULL OUTER JOIN in hash joins.
This is advantageous first because it allows us to hash the smaller table regardless of the outer-join type, and second because hash join can be more flexible than merge join in dealing with arbitrary join quals in a FULL join. For merge join all the join quals have to be mergejoinable, but hash join will work so long as there's at least one hashjoinable qual --- the others can be any condition. (This is true essentially because we don't keep per-inner-tuple match flags in merge join, while hash join can do so.) To do this, we need a has-it-been-matched flag for each tuple in the hashtable, not just one for the current outer tuple. The key idea that makes this practical is that we can store the match flag in the tuple's infomask, since there are lots of bits there that are of no interest for a MinimalTuple. So we aren't increasing the size of the hashtable at all for the feature. To write this without turning the hash code into even more of a pile of spaghetti than it already was, I rewrote ExecHashJoin in a state-machine style, similar to ExecMergeJoin. Other than that decision, it was pretty straightforward.
Diffstat (limited to 'src/include/executor')
-rw-r--r--src/include/executor/hashjoin.h2
-rw-r--r--src/include/executor/nodeHash.h10
2 files changed, 9 insertions, 3 deletions
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,