|
20 | 20 | #include "miscadmin.h"
|
21 | 21 | #include "utils/lsyscache.h"
|
22 | 22 |
|
| 23 | +typedef struct TupleHashEntryData |
| 24 | +{ |
| 25 | + MinimalTuple firstTuple; /* copy of first tuple in this group */ |
| 26 | + uint32 status; /* hash status */ |
| 27 | + uint32 hash; /* hash value (cached) */ |
| 28 | +} TupleHashEntryData; |
| 29 | + |
23 | 30 | static int TupleHashTableMatch(struct tuplehash_hash *tb, const MinimalTuple tuple1, const MinimalTuple tuple2);
|
24 | 31 | static inline uint32 TupleHashTableHash_internal(struct tuplehash_hash *tb,
|
25 | 32 | const MinimalTuple tuple);
|
@@ -196,6 +203,7 @@ BuildTupleHashTable(PlanState *parent,
|
196 | 203 | hashtable->tab_collations = collations;
|
197 | 204 | hashtable->tablecxt = tablecxt;
|
198 | 205 | hashtable->tempcxt = tempcxt;
|
| 206 | + hashtable->additionalsize = additionalsize; |
199 | 207 | hashtable->tableslot = NULL; /* will be made on first lookup */
|
200 | 208 | hashtable->inputslot = NULL;
|
201 | 209 | hashtable->in_hash_expr = NULL;
|
@@ -273,6 +281,15 @@ ResetTupleHashTable(TupleHashTable hashtable)
|
273 | 281 | tuplehash_reset(hashtable->hashtab);
|
274 | 282 | }
|
275 | 283 |
|
| 284 | +/* |
| 285 | + * Return size of the hash bucket. Useful for estimating memory usage. |
| 286 | + */ |
| 287 | +size_t |
| 288 | +TupleHashEntrySize(void) |
| 289 | +{ |
| 290 | + return sizeof(TupleHashEntryData); |
| 291 | +} |
| 292 | + |
276 | 293 | /*
|
277 | 294 | * Find or create a hashtable entry for the tuple group containing the
|
278 | 295 | * given tuple. The tuple must be the same type as the hashtable entries.
|
@@ -339,6 +356,24 @@ TupleHashTableHash(TupleHashTable hashtable, TupleTableSlot *slot)
|
339 | 356 | return hash;
|
340 | 357 | }
|
341 | 358 |
|
| 359 | +MinimalTuple |
| 360 | +TupleHashEntryGetTuple(TupleHashEntry entry) |
| 361 | +{ |
| 362 | + return entry->firstTuple; |
| 363 | +} |
| 364 | + |
| 365 | +/* |
| 366 | + * Get a pointer into the additional space allocated for this entry. The |
| 367 | + * amount of space available is the additionalsize specified to |
| 368 | + * BuildTupleHashTable(). If additionalsize was specified as zero, no |
| 369 | + * additional space is available and this function should not be called. |
| 370 | + */ |
| 371 | +void * |
| 372 | +TupleHashEntryGetAdditional(TupleHashEntry entry) |
| 373 | +{ |
| 374 | + return (char *) entry->firstTuple + MAXALIGN(entry->firstTuple->t_len); |
| 375 | +} |
| 376 | + |
342 | 377 | /*
|
343 | 378 | * A variant of LookupTupleHashEntry for callers that have already computed
|
344 | 379 | * the hash value.
|
@@ -477,13 +512,31 @@ LookupTupleHashEntry_internal(TupleHashTable hashtable, TupleTableSlot *slot,
|
477 | 512 | }
|
478 | 513 | else
|
479 | 514 | {
|
| 515 | + MinimalTuple firstTuple; |
| 516 | + size_t totalsize; /* including alignment and additionalsize */ |
| 517 | + |
480 | 518 | /* created new entry */
|
481 | 519 | *isnew = true;
|
482 | 520 | /* zero caller data */
|
483 |
| - entry->additional = NULL; |
484 | 521 | MemoryContextSwitchTo(hashtable->tablecxt);
|
| 522 | + |
485 | 523 | /* Copy the first tuple into the table context */
|
486 |
| - entry->firstTuple = ExecCopySlotMinimalTuple(slot); |
| 524 | + firstTuple = ExecCopySlotMinimalTuple(slot); |
| 525 | + |
| 526 | + /* |
| 527 | + * Allocate additional space right after the MinimalTuple of size |
| 528 | + * additionalsize. The caller can get a pointer to this data with |
| 529 | + * TupleHashEntryGetAdditional(), and store arbitrary data there. |
| 530 | + * |
| 531 | + * This avoids the need to store an extra pointer or allocate an |
| 532 | + * additional chunk, which would waste memory. |
| 533 | + */ |
| 534 | + totalsize = MAXALIGN(firstTuple->t_len) + hashtable->additionalsize; |
| 535 | + firstTuple = repalloc(firstTuple, totalsize); |
| 536 | + memset((char *) firstTuple + firstTuple->t_len, 0, |
| 537 | + totalsize - firstTuple->t_len); |
| 538 | + |
| 539 | + entry->firstTuple = firstTuple; |
487 | 540 | }
|
488 | 541 | }
|
489 | 542 | else
|
|
0 commit comments