v7-0002-Add-foreach_hash-macro.patch
text/x-patch
Filename: v7-0002-Add-foreach_hash-macro.patch
Type: text/x-patch
Part: 1
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v7-0002
Subject: Add foreach_hash macro
| File | + | − |
|---|---|---|
| src/backend/utils/hash/dynahash.c | 14 | 1 |
| src/include/utils/hsearch.h | 56 | 0 |
From 89439f4949a21208aca09aaf7202e7fbf2c3e3ac Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <postgres@jeltef.nl>
Date: Thu, 4 Dec 2025 15:39:00 +0100
Subject: [PATCH v7 2/5] Add foreach_hash macro
For lists we've had a new foreach style macros since 14dd0f27d7. This
adds a similar macro for hash tables. This new foreach_hash macro makes
iterating over the items in an HTAB as simple as iterating over the
items in a List. The only additional thing to keep in mind is that when
exiting the loop early you need to call foreach_hash_term.
---
src/backend/utils/hash/dynahash.c | 15 ++++++++-
src/include/utils/hsearch.h | 56 +++++++++++++++++++++++++++++++
2 files changed, 70 insertions(+), 1 deletion(-)
diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c
index c0faaaf61da..29fc8f460bb 100644
--- a/src/backend/utils/hash/dynahash.c
+++ b/src/backend/utils/hash/dynahash.c
@@ -1462,7 +1462,7 @@ hash_get_num_entries(HTAB *hashp)
}
/*
- * hash_seq_init/_search/_term
+ * hash_seq_init/_new/_search/_term
* Sequentially search through hash table and return
* all the elements one by one, return NULL when no more.
*
@@ -1496,6 +1496,19 @@ hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
register_seq_scan(hashp);
}
+/*
+ * Same as hash_seq_init(), but returns the status struct instead of taking a
+ * pointer.
+ */
+HASH_SEQ_STATUS
+hash_seq_new(HTAB *hashp)
+{
+ HASH_SEQ_STATUS status;
+
+ hash_seq_init(&status, hashp);
+ return status;
+}
+
/*
* Same as above but scan by the given hash value.
* See also hash_seq_search().
diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h
index 71c9780132f..33e228e32e5 100644
--- a/src/include/utils/hsearch.h
+++ b/src/include/utils/hsearch.h
@@ -279,6 +279,61 @@ typedef struct
uint32 hashvalue; /* hashvalue to start seqscan over hash */
} HASH_SEQ_STATUS;
+/*
+ * foreach_hash - iterate over all entries in a hash table
+ *
+ * This macro simplifies hash table iteration by combining hash_seq_init
+ * and hash_seq_search into a single for-loop construct.
+ *
+ * Usage:
+ * foreach_hash(MyEntry, entry, my_hashtable)
+ * {
+ * // use entry
+ * }
+ *
+ * This replaces the more verbose pattern:
+ * HASH_SEQ_STATUS status;
+ * MyEntry *entry;
+ * hash_seq_init(&status, my_hashtable);
+ * while ((entry = (MyEntry *) hash_seq_search(&status)) != NULL)
+ * {
+ * // use entry
+ * }
+ *
+ * For early termination, use foreach_hash_term() before break:
+ * foreach_hash(MyEntry, entry, my_hashtable)
+ * {
+ * if (found_it)
+ * {
+ * foreach_hash_term(entry);
+ * break;
+ * }
+ * }
+ */
+#define foreach_hash(type, var, htab) \
+ for (type *var = NULL, *var##__outerloop = (type *) 1; \
+ var##__outerloop; \
+ var##__outerloop = 0) \
+ for (HASH_SEQ_STATUS var##__status = hash_seq_new(htab); \
+ (var = (type *) hash_seq_search(&var##__status)) != NULL; )
+
+/*
+ * foreach_hash_term - terminate a foreach_hash loop early
+ *
+ * Call this before 'break' to properly clean up the hash scan.
+ */
+#define foreach_hash_term(var) hash_seq_term(&var##__status)
+
+/*
+ * foreach_hash_restart - restart iteration from the beginning
+ *
+ * Use when modifications during iteration may have invalidated the scan.
+ * The next iteration will start from the first entry again.
+ */
+#define foreach_hash_restart(var, htab) \
+ (hash_seq_term(&var##__status), \
+ hash_seq_init(&var##__status, htab))
+
/*
* prototypes for functions in dynahash.c
*/
@@ -299,6 +354,7 @@ extern bool hash_update_hash_key(HTAB *hashp, void *existingEntry,
const void *newKeyPtr);
extern int64 hash_get_num_entries(HTAB *hashp);
extern void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp);
+extern HASH_SEQ_STATUS hash_seq_new(HTAB *hashp);
extern void hash_seq_init_with_hash_value(HASH_SEQ_STATUS *status,
HTAB *hashp,
uint32 hashvalue);
--
2.52.0