summaryrefslogtreecommitdiff
path: root/src/backend/utils/cache
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/cache')
-rw-r--r--src/backend/utils/cache/lsyscache.c62
-rw-r--r--src/backend/utils/cache/syscache.c12
-rw-r--r--src/backend/utils/cache/typcache.c98
3 files changed, 164 insertions, 8 deletions
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index 204bcd03c0b..ad92636f7f1 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -2611,6 +2611,16 @@ type_is_range(Oid typid)
}
/*
+ * type_is_multirange
+ * Returns true if the given type is a multirange type.
+ */
+bool
+type_is_multirange(Oid typid)
+{
+ return (get_typtype(typid) == TYPTYPE_MULTIRANGE);
+}
+
+/*
* get_type_category_preferred
*
* Given the type OID, fetch its category and preferred-type status.
@@ -3308,7 +3318,7 @@ get_namespace_name_or_temp(Oid nspid)
return get_namespace_name(nspid);
}
-/* ---------- PG_RANGE CACHE ---------- */
+/* ---------- PG_RANGE CACHES ---------- */
/*
* get_range_subtype
@@ -3361,6 +3371,56 @@ get_range_collation(Oid rangeOid)
return InvalidOid;
}
+/*
+ * get_range_multirange
+ * Returns the multirange type of a given range type
+ *
+ * Returns InvalidOid if the type is not a range type.
+ */
+Oid
+get_range_multirange(Oid rangeOid)
+{
+ HeapTuple tp;
+
+ tp = SearchSysCache1(RANGETYPE, ObjectIdGetDatum(rangeOid));
+ if (HeapTupleIsValid(tp))
+ {
+ Form_pg_range rngtup = (Form_pg_range) GETSTRUCT(tp);
+ Oid result;
+
+ result = rngtup->rngmultitypid;
+ ReleaseSysCache(tp);
+ return result;
+ }
+ else
+ return InvalidOid;
+}
+
+/*
+ * get_multirange_range
+ * Returns the range type of a given multirange
+ *
+ * Returns InvalidOid if the type is not a multirange.
+ */
+Oid
+get_multirange_range(Oid multirangeOid)
+{
+ HeapTuple tp;
+
+ tp = SearchSysCache1(RANGEMULTIRANGE, ObjectIdGetDatum(multirangeOid));
+ if (HeapTupleIsValid(tp))
+ {
+ Form_pg_range rngtup = (Form_pg_range) GETSTRUCT(tp);
+ Oid result;
+
+ result = rngtup->rngtypid;
+ ReleaseSysCache(tp);
+ return result;
+ }
+ else
+ return InvalidOid;
+}
+
/* ---------- PG_INDEX CACHE ---------- */
/*
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index 809b27a038f..89f08a4f43c 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -650,6 +650,18 @@ static const struct cachedesc cacheinfo[] = {
},
64
},
+ {RangeRelationId, /* RANGEMULTIRANGE */
+ RangeMultirangeTypidIndexId,
+ 1,
+ {
+ Anum_pg_range_rngmultitypid,
+ 0,
+ 0,
+ 0
+ },
+ 4
+ },
+
{RangeRelationId, /* RANGETYPE */
RangeTypidIndexId,
1,
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'.