aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/arrayfuncs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/arrayfuncs.c')
-rw-r--r--src/backend/utils/adt/arrayfuncs.c36
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;