diff options
Diffstat (limited to 'src/backend/utils/adt/arrayfuncs.c')
-rw-r--r-- | src/backend/utils/adt/arrayfuncs.c | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index 04d487c5442..bc2f30bae15 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -29,6 +29,7 @@ #include "utils/arrayaccess.h" #include "utils/builtins.h" #include "utils/datum.h" +#include "utils/fmgroids.h" #include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/selfuncs.h" @@ -3973,13 +3974,46 @@ hash_array(PG_FUNCTION_ARGS) { typentry = lookup_type_cache(element_type, TYPECACHE_HASH_PROC_FINFO); - if (!OidIsValid(typentry->hash_proc_finfo.fn_oid)) + if (!OidIsValid(typentry->hash_proc_finfo.fn_oid) && element_type != RECORDOID) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("could not identify a hash function for type %s", format_type_be(element_type)))); + + /* + * The type cache doesn't believe that record is hashable (see + * cache_record_field_properties()), but since we're here, we're + * committed to hashing, so we can assume it does. Worst case, if any + * components of the record don't support hashing, we will fail at + * execution. + */ + if (element_type == RECORDOID) + { + MemoryContext oldcontext; + TypeCacheEntry *record_typentry; + + oldcontext = MemoryContextSwitchTo(CacheMemoryContext); + + /* + * Make fake type cache entry structure. Note that we can't just + * modify typentry, since that points directly into the type cache. + */ + record_typentry = palloc(sizeof(*record_typentry)); + + /* fill in what we need below */ + record_typentry->typlen = typentry->typlen; + record_typentry->typbyval = typentry->typbyval; + record_typentry->typalign = typentry->typalign; + fmgr_info(F_HASH_RECORD, &record_typentry->hash_proc_finfo); + + MemoryContextSwitchTo(oldcontext); + + typentry = record_typentry; + } + fcinfo->flinfo->fn_extra = (void *) typentry; } + typlen = typentry->typlen; typbyval = typentry->typbyval; typalign = typentry->typalign; |