1
0
mirror of https://github.com/postgres/postgres.git synced 2025-12-21 05:21:08 +03:00

Improve hash_create()'s API for some added robustness.

Invent a new flag bit HASH_STRINGS to specify C-string hashing, which
was formerly the default; and add assertions insisting that exactly
one of the bits HASH_STRINGS, HASH_BLOBS, and HASH_FUNCTION be set.
This is in hopes of preventing recurrences of the type of oversight
fixed in commit a1b8aa1e4 (i.e., mistakenly omitting HASH_BLOBS).

Also, when HASH_STRINGS is specified, insist that the keysize be
more than 8 bytes.  This is a heuristic, but it should catch
accidental use of HASH_STRINGS for integer or pointer keys.
(Nearly all existing use-cases set the keysize to NAMEDATALEN or
more, so there's little reason to think this restriction should
be problematic.)

Tweak hash_create() to insist that the HASH_ELEM flag be set, and
remove the defaults it had for keysize and entrysize.  Since those
defaults were undocumented and basically useless, no callers
omitted HASH_ELEM anyway.

Also, remove memset's zeroing the HASHCTL parameter struct from
those callers that had one.  This has never been really necessary,
and while it wasn't a bad coding convention it was confusing that
some callers did it and some did not.  We might as well save a few
cycles by standardizing on "not".

Also improve the documentation for hash_create().

In passing, improve reinit.c's usage of a hash table by storing
the key as a binary Oid rather than a string; and, since that's
a temporary hash table, allocate it in CurrentMemoryContext for
neatness.

Discussion: https://postgr.es/m/590625.1607878171@sss.pgh.pa.us
This commit is contained in:
Tom Lane
2020-12-15 11:38:53 -05:00
parent a58db3aa10
commit b3817f5f77
63 changed files with 112 additions and 158 deletions

View File

@@ -64,25 +64,36 @@ typedef struct HTAB HTAB;
/* Only those fields indicated by hash_flags need be set */
typedef struct HASHCTL
{
/* Used if HASH_PARTITION flag is set: */
long num_partitions; /* # partitions (must be power of 2) */
/* Used if HASH_SEGMENT flag is set: */
long ssize; /* segment size */
/* Used if HASH_DIRSIZE flag is set: */
long dsize; /* (initial) directory size */
long max_dsize; /* limit to dsize if dir size is limited */
/* Used if HASH_ELEM flag is set (which is now required): */
Size keysize; /* hash key length in bytes */
Size entrysize; /* total user element size in bytes */
/* Used if HASH_FUNCTION flag is set: */
HashValueFunc hash; /* hash function */
/* Used if HASH_COMPARE flag is set: */
HashCompareFunc match; /* key comparison function */
/* Used if HASH_KEYCOPY flag is set: */
HashCopyFunc keycopy; /* key copying function */
/* Used if HASH_ALLOC flag is set: */
HashAllocFunc alloc; /* memory allocator */
/* Used if HASH_CONTEXT flag is set: */
MemoryContext hcxt; /* memory context to use for allocations */
/* Used if HASH_SHARED_MEM flag is set: */
HASHHDR *hctl; /* location of header in shared mem */
} HASHCTL;
/* Flags to indicate which parameters are supplied */
/* Flag bits for hash_create; most indicate which parameters are supplied */
#define HASH_PARTITION 0x0001 /* Hashtable is used w/partitioned locking */
#define HASH_SEGMENT 0x0002 /* Set segment size */
#define HASH_DIRSIZE 0x0004 /* Set directory size (initial and max) */
#define HASH_ELEM 0x0010 /* Set keysize and entrysize */
#define HASH_ELEM 0x0008 /* Set keysize and entrysize (now required!) */
#define HASH_STRINGS 0x0010 /* Select support functions for string keys */
#define HASH_BLOBS 0x0020 /* Select support functions for binary keys */
#define HASH_FUNCTION 0x0040 /* Set user defined hash function */
#define HASH_COMPARE 0x0080 /* Set user defined comparison function */
@@ -93,7 +104,6 @@ typedef struct HASHCTL
#define HASH_ATTACH 0x1000 /* Do not initialize hctl */
#define HASH_FIXED_SIZE 0x2000 /* Initial size is a hard limit */
/* max_dsize value to indicate expansible directory */
#define NO_MAX_DSIZE (-1)
@@ -116,13 +126,9 @@ typedef struct
/*
* prototypes for functions in dynahash.c
*
* Note: It is deprecated for callers of hash_create to explicitly specify
* string_hash, tag_hash, uint32_hash, or oid_hash. Just set HASH_BLOBS or
* not. Use HASH_FUNCTION only when you want something other than those.
*/
extern HTAB *hash_create(const char *tabname, long nelem,
HASHCTL *info, int flags);
const HASHCTL *info, int flags);
extern void hash_destroy(HTAB *hashp);
extern void hash_stats(const char *where, HTAB *hashp);
extern void *hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action,