*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.86 2004/08/29 04:12:31 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.87 2004/09/22 19:13:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* ----------------------------------------------------------------
* ExecHash
*
- * build hash table for hashjoin, all do partitioning if more
- * than one batches are required.
+ * build hash table for hashjoin, doing partitioning if more
+ * than one batch is required.
* ----------------------------------------------------------------
*/
TupleTableSlot *
slot = ExecProcNode(outerNode);
if (TupIsNull(slot))
break;
+ hashtable->hashNonEmpty = true;
econtext->ecxt_innertuple = slot;
ExecHashTableInsert(hashtable, econtext, hashkeys);
ExecClearTuple(slot);
/* ----------------------------------------------------------------
* ExecHashTableCreate
*
- * create a hashtable in shared memory for hashjoin.
+ * create an empty hashtable data structure for hashjoin.
* ----------------------------------------------------------------
*/
HashJoinTable
* The hashtable control block is just palloc'd from the executor's
* per-query memory context.
*/
- hashtable = (HashJoinTable) palloc(sizeof(HashTableData));
+ hashtable = (HashJoinTable) palloc(sizeof(HashJoinTableData));
hashtable->nbuckets = nbuckets;
hashtable->totalbuckets = totalbuckets;
hashtable->buckets = NULL;
hashtable->nbatch = nbatch;
hashtable->curbatch = 0;
+ hashtable->hashNonEmpty = false;
hashtable->innerBatchFile = NULL;
hashtable->outerBatchFile = NULL;
hashtable->innerBatchSize = NULL;
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeHashjoin.c,v 1.65 2004/09/17 18:28:53 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeHashjoin.c,v 1.66 2004/09/22 19:13:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
hashNode->hashtable = hashtable;
(void) ExecProcNode((PlanState *) hashNode);
+ /*
+ * If the inner relation is completely empty, and we're not doing
+ * an outer join, we can quit without scanning the outer relation.
+ */
+ if (!hashtable->hashNonEmpty && node->js.jointype != JOIN_LEFT)
+ {
+ ExecHashTableDestroy(hashtable);
+ node->hj_HashTable = NULL;
+ return NULL;
+ }
+
/*
* Open temp files for outer batches, if needed. Note that file
* buffers are palloc'd in regular executor context.
}
/*
- * Now get an outer tuple and probe into the hash table for matches
+ * run the hash join process
*/
- outerTupleSlot = node->js.ps.ps_OuterTupleSlot;
-
for (;;)
{
/*
* Only the joinquals determine MatchedOuter status, but all
* quals must pass to actually return the tuple.
*/
- if (ExecQual(joinqual, econtext, false))
+ if (joinqual == NIL || ExecQual(joinqual, econtext, false))
{
node->hj_MatchedOuter = true;
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/executor/hashjoin.h,v 1.32 2004/08/29 04:13:06 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/executor/hashjoin.h,v 1.33 2004/09/22 19:13:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
typedef HashJoinTupleData *HashJoinTuple;
-typedef struct HashTableData
+typedef struct HashJoinTableData
{
int nbuckets; /* buckets in use during this batch */
int totalbuckets; /* total number of (virtual) buckets */
int nbatch; /* number of batches; 0 means 1-pass join */
int curbatch; /* current batch #, or 0 during 1st pass */
+ bool hashNonEmpty; /* did inner plan produce any rows? */
+
/*
* all these arrays are allocated for the life of the hash join, but
* only if nbatch > 0:
MemoryContext hashCxt; /* context for whole-hash-join storage */
MemoryContext batchCxt; /* context for this-batch-only storage */
-} HashTableData;
+} HashJoinTableData;
-typedef HashTableData *HashJoinTable;
+typedef HashJoinTableData *HashJoinTable;
#endif /* HASHJOIN_H */