diff options
Diffstat (limited to 'src/backend/utils/cache/typcache.c')
-rw-r--r-- | src/backend/utils/cache/typcache.c | 98 |
1 files changed, 91 insertions, 7 deletions
diff --git a/src/backend/utils/cache/typcache.c b/src/backend/utils/cache/typcache.c index 1e331098c0d..8c97ef39557 100644 --- a/src/backend/utils/cache/typcache.c +++ b/src/backend/utils/cache/typcache.c @@ -287,6 +287,7 @@ static uint64 tupledesc_id_counter = INVALID_TUPLEDESC_IDENTIFIER; static void load_typcache_tupdesc(TypeCacheEntry *typentry); static void load_rangetype_info(TypeCacheEntry *typentry); +static void load_multirangetype_info(TypeCacheEntry *typentry); static void load_domaintype_info(TypeCacheEntry *typentry); static int dcs_cmp(const void *a, const void *b); static void decr_dcc_refcount(DomainConstraintCache *dcc); @@ -305,6 +306,9 @@ static void cache_record_field_properties(TypeCacheEntry *typentry); static bool range_element_has_hashing(TypeCacheEntry *typentry); static bool range_element_has_extended_hashing(TypeCacheEntry *typentry); static void cache_range_element_properties(TypeCacheEntry *typentry); +static bool multirange_element_has_hashing(TypeCacheEntry *typentry); +static bool multirange_element_has_extended_hashing(TypeCacheEntry *typentry); +static void cache_multirange_element_properties(TypeCacheEntry *typentry); static void TypeCacheRelCallback(Datum arg, Oid relid); static void TypeCacheTypCallback(Datum arg, int cacheid, uint32 hashvalue); static void TypeCacheOpcCallback(Datum arg, int cacheid, uint32 hashvalue); @@ -557,8 +561,8 @@ lookup_type_cache(Oid type_id, int flags) * to see if the element type or column types support equality. If * not, array_eq or record_eq would fail at runtime, so we don't want * to report that the type has equality. (We can omit similar - * checking for ranges because ranges can't be created in the first - * place unless their subtypes support equality.) + * checking for ranges and multiranges because ranges can't be created + * in the first place unless their subtypes support equality.) */ if (eq_opr == ARRAY_EQ_OP && !array_element_has_equality(typentry)) @@ -595,7 +599,7 @@ lookup_type_cache(Oid type_id, int flags) /* * As above, make sure array_cmp or record_cmp will succeed; but again - * we need no special check for ranges. + * we need no special check for ranges or multiranges. */ if (lt_opr == ARRAY_LT_OP && !array_element_has_compare(typentry)) @@ -620,7 +624,7 @@ lookup_type_cache(Oid type_id, int flags) /* * As above, make sure array_cmp or record_cmp will succeed; but again - * we need no special check for ranges. + * we need no special check for ranges or multiranges. */ if (gt_opr == ARRAY_GT_OP && !array_element_has_compare(typentry)) @@ -645,7 +649,7 @@ lookup_type_cache(Oid type_id, int flags) /* * As above, make sure array_cmp or record_cmp will succeed; but again - * we need no special check for ranges. + * we need no special check for ranges or multiranges. */ if (cmp_proc == F_BTARRAYCMP && !array_element_has_compare(typentry)) @@ -695,6 +699,13 @@ lookup_type_cache(Oid type_id, int flags) !range_element_has_hashing(typentry)) hash_proc = InvalidOid; + /* + * Likewise for hash_multirange. + */ + if (hash_proc == F_HASH_MULTIRANGE && + !multirange_element_has_hashing(typentry)) + hash_proc = InvalidOid; + /* Force update of hash_proc_finfo only if we're changing state */ if (typentry->hash_proc != hash_proc) typentry->hash_proc_finfo.fn_oid = InvalidOid; @@ -737,6 +748,13 @@ lookup_type_cache(Oid type_id, int flags) !range_element_has_extended_hashing(typentry)) hash_extended_proc = InvalidOid; + /* + * Likewise for hash_multirange_extended. + */ + if (hash_extended_proc == F_HASH_MULTIRANGE_EXTENDED && + !multirange_element_has_extended_hashing(typentry)) + hash_extended_proc = InvalidOid; + /* Force update of proc finfo only if we're changing state */ if (typentry->hash_extended_proc != hash_extended_proc) typentry->hash_extended_proc_finfo.fn_oid = InvalidOid; @@ -817,6 +835,16 @@ lookup_type_cache(Oid type_id, int flags) } /* + * If requested, get information about a multirange type + */ + if ((flags & TYPECACHE_MULTIRANGE_INFO) && + typentry->rngtype == NULL && + typentry->typtype == TYPTYPE_MULTIRANGE) + { + load_multirangetype_info(typentry); + } + + /* * If requested, get information about a domain type */ if ((flags & TYPECACHE_DOMAIN_BASE_INFO) && @@ -927,6 +955,22 @@ load_rangetype_info(TypeCacheEntry *typentry) typentry->rngelemtype = lookup_type_cache(subtypeOid, 0); } +/* + * load_multirangetype_info --- helper routine to set up multirange type + * information + */ +static void +load_multirangetype_info(TypeCacheEntry *typentry) +{ + Oid rangetypeOid; + + rangetypeOid = get_multirange_range(typentry->type_id); + if (!OidIsValid(rangetypeOid)) + elog(ERROR, "cache lookup failed for multirange type %u", + typentry->type_id); + + typentry->rngtype = lookup_type_cache(rangetypeOid, TYPECACHE_RANGE_INFO); +} /* * load_domaintype_info --- helper routine to set up domain constraint info @@ -1559,11 +1603,11 @@ cache_record_field_properties(TypeCacheEntry *typentry) } /* - * Likewise, some helper functions for range types. + * Likewise, some helper functions for range and multirange types. * * We can borrow the flag bits for array element properties to use for range * element properties, since those flag bits otherwise have no use in a - * range type's typcache entry. + * range or multirange type's typcache entry. */ static bool @@ -1606,6 +1650,46 @@ cache_range_element_properties(TypeCacheEntry *typentry) typentry->flags |= TCFLAGS_CHECKED_ELEM_PROPERTIES; } +static bool +multirange_element_has_hashing(TypeCacheEntry *typentry) +{ + if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES)) + cache_multirange_element_properties(typentry); + return (typentry->flags & TCFLAGS_HAVE_ELEM_HASHING) != 0; +} + +static bool +multirange_element_has_extended_hashing(TypeCacheEntry *typentry) +{ + if (!(typentry->flags & TCFLAGS_CHECKED_ELEM_PROPERTIES)) + cache_multirange_element_properties(typentry); + return (typentry->flags & TCFLAGS_HAVE_ELEM_EXTENDED_HASHING) != 0; +} + +static void +cache_multirange_element_properties(TypeCacheEntry *typentry) +{ + /* load up range link if we didn't already */ + if (typentry->rngtype == NULL && + typentry->typtype == TYPTYPE_MULTIRANGE) + load_multirangetype_info(typentry); + + if (typentry->rngtype != NULL && typentry->rngtype->rngelemtype != NULL) + { + TypeCacheEntry *elementry; + + /* might need to calculate subtype's hash function properties */ + elementry = lookup_type_cache(typentry->rngtype->rngelemtype->type_id, + TYPECACHE_HASH_PROC | + TYPECACHE_HASH_EXTENDED_PROC); + if (OidIsValid(elementry->hash_proc)) + typentry->flags |= TCFLAGS_HAVE_ELEM_HASHING; + if (OidIsValid(elementry->hash_extended_proc)) + typentry->flags |= TCFLAGS_HAVE_ELEM_EXTENDED_HASHING; + } + typentry->flags |= TCFLAGS_CHECKED_ELEM_PROPERTIES; +} + /* * Make sure that RecordCacheArray and RecordIdentifierArray are large enough * to store 'typmod'. |