mirror of
https://github.com/postgres/postgres.git
synced 2025-06-13 07:41:39 +03:00
Restructure function-internal caching in the range type code.
Move the responsibility for caching specialized information about range types into the type cache, so that the catalog lookups only have to occur once per session. Rearrange APIs a bit so that fn_extra caching is actually effective in the GiST support code. (Use of OidFunctionCallN is bad enough for performance in itself, but it also prevents the function from exploiting fn_extra caching.) The range I/O functions are still not very bright about caching repeated lookups, but that seems like material for a separate patch. Also, avoid unnecessary use of memcpy to fetch/store the range type OID and flags, and don't use the full range_deserialize machinery when all we need to see is the flags value. Also fix API error in range_gist_penalty --- it was failing to set *penalty for any case involving an empty range.
This commit is contained in:
69
src/backend/utils/cache/typcache.c
vendored
69
src/backend/utils/cache/typcache.c
vendored
@ -51,6 +51,7 @@
|
||||
#include "catalog/indexing.h"
|
||||
#include "catalog/pg_enum.h"
|
||||
#include "catalog/pg_operator.h"
|
||||
#include "catalog/pg_range.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "commands/defrem.h"
|
||||
#include "utils/builtins.h"
|
||||
@ -120,6 +121,7 @@ static int32 RecordCacheArrayLen = 0; /* allocated length of array */
|
||||
static int32 NextRecordTypmod = 0; /* number of entries used */
|
||||
|
||||
static void load_typcache_tupdesc(TypeCacheEntry *typentry);
|
||||
static void load_rangetype_info(TypeCacheEntry *typentry);
|
||||
static bool array_element_has_equality(TypeCacheEntry *typentry);
|
||||
static bool array_element_has_compare(TypeCacheEntry *typentry);
|
||||
static bool array_element_has_hashing(TypeCacheEntry *typentry);
|
||||
@ -205,6 +207,7 @@ lookup_type_cache(Oid type_id, int flags)
|
||||
typentry->typlen = typtup->typlen;
|
||||
typentry->typbyval = typtup->typbyval;
|
||||
typentry->typalign = typtup->typalign;
|
||||
typentry->typstorage = typtup->typstorage;
|
||||
typentry->typtype = typtup->typtype;
|
||||
typentry->typrelid = typtup->typrelid;
|
||||
|
||||
@ -448,6 +451,16 @@ lookup_type_cache(Oid type_id, int flags)
|
||||
load_typcache_tupdesc(typentry);
|
||||
}
|
||||
|
||||
/*
|
||||
* If requested, get information about a range type
|
||||
*/
|
||||
if ((flags & TYPECACHE_RANGE_INFO) &&
|
||||
typentry->rngelemtype == NULL &&
|
||||
typentry->typtype == TYPTYPE_RANGE)
|
||||
{
|
||||
load_rangetype_info(typentry);
|
||||
}
|
||||
|
||||
return typentry;
|
||||
}
|
||||
|
||||
@ -479,6 +492,62 @@ load_typcache_tupdesc(TypeCacheEntry *typentry)
|
||||
relation_close(rel, AccessShareLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* load_rangetype_info --- helper routine to set up range type information
|
||||
*/
|
||||
static void
|
||||
load_rangetype_info(TypeCacheEntry *typentry)
|
||||
{
|
||||
Form_pg_range pg_range;
|
||||
HeapTuple tup;
|
||||
Oid subtypeOid;
|
||||
Oid opclassOid;
|
||||
Oid canonicalOid;
|
||||
Oid subdiffOid;
|
||||
Oid opfamilyOid;
|
||||
Oid opcintype;
|
||||
Oid cmpFnOid;
|
||||
|
||||
/* get information from pg_range */
|
||||
tup = SearchSysCache1(RANGETYPE, ObjectIdGetDatum(typentry->type_id));
|
||||
/* should not fail, since we already checked typtype ... */
|
||||
if (!HeapTupleIsValid(tup))
|
||||
elog(ERROR, "cache lookup failed for range type %u",
|
||||
typentry->type_id);
|
||||
pg_range = (Form_pg_range) GETSTRUCT(tup);
|
||||
|
||||
subtypeOid = pg_range->rngsubtype;
|
||||
typentry->rng_collation = pg_range->rngcollation;
|
||||
opclassOid = pg_range->rngsubopc;
|
||||
canonicalOid = pg_range->rngcanonical;
|
||||
subdiffOid = pg_range->rngsubdiff;
|
||||
|
||||
ReleaseSysCache(tup);
|
||||
|
||||
/* get opclass properties and look up the comparison function */
|
||||
opfamilyOid = get_opclass_family(opclassOid);
|
||||
opcintype = get_opclass_input_type(opclassOid);
|
||||
|
||||
cmpFnOid = get_opfamily_proc(opfamilyOid, opcintype, opcintype,
|
||||
BTORDER_PROC);
|
||||
if (!RegProcedureIsValid(cmpFnOid))
|
||||
elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
|
||||
BTORDER_PROC, opcintype, opcintype, opfamilyOid);
|
||||
|
||||
/* set up cached fmgrinfo structs */
|
||||
fmgr_info_cxt(cmpFnOid, &typentry->rng_cmp_proc_finfo,
|
||||
CacheMemoryContext);
|
||||
if (OidIsValid(canonicalOid))
|
||||
fmgr_info_cxt(canonicalOid, &typentry->rng_canonical_finfo,
|
||||
CacheMemoryContext);
|
||||
if (OidIsValid(subdiffOid))
|
||||
fmgr_info_cxt(subdiffOid, &typentry->rng_subdiff_finfo,
|
||||
CacheMemoryContext);
|
||||
|
||||
/* Lastly, set up link to the element type --- this marks data valid */
|
||||
typentry->rngelemtype = lookup_type_cache(subtypeOid, 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* array_element_has_equality and friends are helper routines to check
|
||||
|
Reference in New Issue
Block a user