Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit8daa62a

Browse files
committed
Revert: Avoid looping over all type cache entries in TypeCacheRelCallback()
This commit revertsc14d4ac as the patch design didn't take into accountthat TypeCacheEntry could be invalidated during the lookup_type_cache() call.Reported-by: Alexander LakhinDiscussion:https://postgr.es/m/1927cba4-177e-5c23-cbcc-d444a850304f%40gmail.com
1 parentc14d4ac commit8daa62a

File tree

2 files changed

+44
-232
lines changed

2 files changed

+44
-232
lines changed

‎src/backend/utils/cache/typcache.c

Lines changed: 44 additions & 231 deletions
Original file line numberDiff line numberDiff line change
@@ -77,20 +77,6 @@
7777
/* The main type cache hashtable searched by lookup_type_cache */
7878
staticHTAB*TypeCacheHash=NULL;
7979

80-
/*
81-
* The mapping of relation's OID to the corresponding composite type OID.
82-
* We're keeping the map entry when the corresponding typentry has something
83-
* to clear i.e it has either TCFLAGS_HAVE_PG_TYPE_DATA, or
84-
* TCFLAGS_OPERATOR_FLAGS, or tupdesc.
85-
*/
86-
staticHTAB*RelIdToTypeIdCacheHash=NULL;
87-
88-
typedefstructRelIdToTypeIdCacheEntry
89-
{
90-
Oidrelid;/* OID of the relation */
91-
Oidcomposite_typid;/* OID of the relation's composite type */
92-
}RelIdToTypeIdCacheEntry;
93-
9480
/* List of type cache entries for domain types */
9581
staticTypeCacheEntry*firstDomainTypeEntry=NULL;
9682

@@ -343,8 +329,6 @@ static void shared_record_typmod_registry_detach(dsm_segment *segment,
343329
staticTupleDescfind_or_make_matching_shared_tupledesc(TupleDesctupdesc);
344330
staticdsa_pointershare_tupledesc(dsa_area*area,TupleDesctupdesc,
345331
uint32typmod);
346-
staticvoidinsert_rel_type_cache_if_needed(TypeCacheEntry*typentry);
347-
staticvoiddelete_rel_type_cache_if_needed(TypeCacheEntry*typentry);
348332

349333

350334
/*
@@ -392,13 +376,6 @@ lookup_type_cache(Oid type_id, int flags)
392376
TypeCacheHash=hash_create("Type information cache",64,
393377
&ctl,HASH_ELEM |HASH_FUNCTION);
394378

395-
Assert(RelIdToTypeIdCacheHash==NULL);
396-
397-
ctl.keysize=sizeof(Oid);
398-
ctl.entrysize=sizeof(RelIdToTypeIdCacheEntry);
399-
RelIdToTypeIdCacheHash=hash_create("Map from relid to OID of cached composite type",64,
400-
&ctl,HASH_ELEM |HASH_BLOBS);
401-
402379
/* Also set up callbacks for SI invalidations */
403380
CacheRegisterRelcacheCallback(TypeCacheRelCallback, (Datum)0);
404381
CacheRegisterSyscacheCallback(TYPEOID,TypeCacheTypCallback, (Datum)0);
@@ -410,8 +387,6 @@ lookup_type_cache(Oid type_id, int flags)
410387
CreateCacheMemoryContext();
411388
}
412389

413-
Assert(TypeCacheHash!=NULL&&RelIdToTypeIdCacheHash!=NULL);
414-
415390
/* Try to look up an existing entry */
416391
typentry= (TypeCacheEntry*)hash_search(TypeCacheHash,
417392
&type_id,
@@ -463,7 +438,6 @@ lookup_type_cache(Oid type_id, int flags)
463438
typentry->typelem=typtup->typelem;
464439
typentry->typcollation=typtup->typcollation;
465440
typentry->flags |=TCFLAGS_HAVE_PG_TYPE_DATA;
466-
insert_rel_type_cache_if_needed(typentry);
467441

468442
/* If it's a domain, immediately thread it into the domain cache list */
469443
if (typentry->typtype==TYPTYPE_DOMAIN)
@@ -509,7 +483,6 @@ lookup_type_cache(Oid type_id, int flags)
509483
typentry->typelem=typtup->typelem;
510484
typentry->typcollation=typtup->typcollation;
511485
typentry->flags |=TCFLAGS_HAVE_PG_TYPE_DATA;
512-
insert_rel_type_cache_if_needed(typentry);
513486

514487
ReleaseSysCache(tp);
515488
}
@@ -2308,53 +2281,6 @@ SharedRecordTypmodRegistryAttach(SharedRecordTypmodRegistry *registry)
23082281
CurrentSession->shared_typmod_table=typmod_table;
23092282
}
23102283

2311-
/*
2312-
* InvalidateCompositeTypeCacheEntry
2313-
*Invalidate particular TypeCacheEntry on Relcache inval callback
2314-
*
2315-
* Delete the cached tuple descriptor (if any) for the given composite
2316-
* type, and reset whatever info we have cached about the composite type's
2317-
* comparability.
2318-
*/
2319-
staticvoid
2320-
InvalidateCompositeTypeCacheEntry(TypeCacheEntry*typentry)
2321-
{
2322-
boolhadTupDescOrOpclass;
2323-
2324-
Assert(typentry->typtype==TYPTYPE_COMPOSITE&&
2325-
OidIsValid(typentry->typrelid));
2326-
2327-
hadTupDescOrOpclass= (typentry->tupDesc!=NULL)||
2328-
(typentry->flags&TCFLAGS_OPERATOR_FLAGS);
2329-
2330-
/* Delete tupdesc if we have it */
2331-
if (typentry->tupDesc!=NULL)
2332-
{
2333-
/*
2334-
* Release our refcount and free the tupdesc if none remain. We can't
2335-
* use DecrTupleDescRefCount here because this reference is not logged
2336-
* by the current resource owner.
2337-
*/
2338-
Assert(typentry->tupDesc->tdrefcount>0);
2339-
if (--typentry->tupDesc->tdrefcount==0)
2340-
FreeTupleDesc(typentry->tupDesc);
2341-
typentry->tupDesc=NULL;
2342-
2343-
/*
2344-
* Also clear tupDesc_identifier, so that anyone watching it will
2345-
* realize that the tupdesc has changed.
2346-
*/
2347-
typentry->tupDesc_identifier=0;
2348-
}
2349-
2350-
/* Reset equality/comparison/hashing validity information */
2351-
typentry->flags &= ~TCFLAGS_OPERATOR_FLAGS;
2352-
2353-
/* Call check_delete_rel_type_cache() if we actually cleared something */
2354-
if (hadTupDescOrOpclass)
2355-
delete_rel_type_cache_if_needed(typentry);
2356-
}
2357-
23582284
/*
23592285
* TypeCacheRelCallback
23602286
*Relcache inval callback function
@@ -2364,55 +2290,63 @@ InvalidateCompositeTypeCacheEntry(TypeCacheEntry *typentry)
23642290
* whatever info we have cached about the composite type's comparability.
23652291
*
23662292
* This is called when a relcache invalidation event occurs for the given
2367-
* relid. We can't use syscache to find a type corresponding to the given
2368-
* relation because the code can be called outside of transaction. Thus we use
2369-
* the RelIdToTypeIdCacheHash map to locate appropriate typcache entry.
2293+
* relid. We must scan the whole typcache hash since we don't know the
2294+
* type OID corresponding to the relid. We could do a direct search if this
2295+
* were a syscache-flush callback on pg_type, but then we would need all
2296+
* ALTER-TABLE-like commands that could modify a rowtype to issue syscache
2297+
* invals against the rel's pg_type OID. The extra SI signaling could very
2298+
* well cost more than we'd save, since in most usages there are not very
2299+
* many entries in a backend's typcache. The risk of bugs-of-omission seems
2300+
* high, too.
2301+
*
2302+
* Another possibility, with only localized impact, is to maintain a second
2303+
* hashtable that indexes composite-type typcache entries by their typrelid.
2304+
* But it's still not clear it's worth the trouble.
23702305
*/
23712306
staticvoid
23722307
TypeCacheRelCallback(Datumarg,Oidrelid)
23732308
{
2309+
HASH_SEQ_STATUSstatus;
23742310
TypeCacheEntry*typentry;
23752311

2376-
/*
2377-
* RelIdToTypeIdCacheHash and TypeCacheHash should exist, otherwise this
2378-
* callback wouldn't be registered
2379-
*/
2380-
if (OidIsValid(relid))
2312+
/* TypeCacheHash must exist, else this callback wouldn't be registered */
2313+
hash_seq_init(&status,TypeCacheHash);
2314+
while ((typentry= (TypeCacheEntry*)hash_seq_search(&status))!=NULL)
23812315
{
2382-
RelIdToTypeIdCacheEntry*relentry;
2383-
2384-
/*
2385-
* Find an RelIdToTypeIdCacheHash entry, which should exist as soon as
2386-
* corresponding typcache entry has something to clean.
2387-
*/
2388-
relentry= (RelIdToTypeIdCacheEntry*)hash_search(RelIdToTypeIdCacheHash,
2389-
&relid,
2390-
HASH_FIND,NULL);
2391-
2392-
if (relentry!=NULL)
2316+
if (typentry->typtype==TYPTYPE_COMPOSITE)
23932317
{
2394-
typentry= (TypeCacheEntry*)hash_search(TypeCacheHash,
2395-
&relentry->composite_typid,
2396-
HASH_FIND,NULL);
2318+
/* Skip if no match, unless we're zapping all composite types */
2319+
if (relid!=typentry->typrelid&&relid!=InvalidOid)
2320+
continue;
23972321

2398-
if (typentry!=NULL)
2322+
/* Delete tupdesc if we have it */
2323+
if (typentry->tupDesc!=NULL)
23992324
{
2400-
Assert(typentry->typtype==TYPTYPE_COMPOSITE);
2401-
Assert(relid==typentry->typrelid);
2325+
/*
2326+
* Release our refcount, and free the tupdesc if none remain.
2327+
* (Can't use DecrTupleDescRefCount because this reference is
2328+
* not logged in current resource owner.)
2329+
*/
2330+
Assert(typentry->tupDesc->tdrefcount>0);
2331+
if (--typentry->tupDesc->tdrefcount==0)
2332+
FreeTupleDesc(typentry->tupDesc);
2333+
typentry->tupDesc=NULL;
24022334

2403-
InvalidateCompositeTypeCacheEntry(typentry);
2335+
/*
2336+
* Also clear tupDesc_identifier, so that anything watching
2337+
* that will realize that the tupdesc has possibly changed.
2338+
* (Alternatively, we could specify that to detect possible
2339+
* tupdesc change, one must check for tupDesc != NULL as well
2340+
* as tupDesc_identifier being the same as what was previously
2341+
* seen. That seems error-prone.)
2342+
*/
2343+
typentry->tupDesc_identifier=0;
24042344
}
2405-
}
24062345

2407-
/*
2408-
* Visit all the domain types sequentially. Typically this shouldn't
2409-
* affect performance since domain types are less tended to bloat.
2410-
* Domain types are created manually, unlike composite types which are
2411-
* automatically created for every temporary table.
2412-
*/
2413-
for (typentry=firstDomainTypeEntry;
2414-
typentry!=NULL;
2415-
typentry=typentry->nextDomain)
2346+
/* Reset equality/comparison/hashing validity information */
2347+
typentry->flags &= ~TCFLAGS_OPERATOR_FLAGS;
2348+
}
2349+
elseif (typentry->typtype==TYPTYPE_DOMAIN)
24162350
{
24172351
/*
24182352
* If it's domain over composite, reset flags. (We don't bother
@@ -2424,36 +2358,6 @@ TypeCacheRelCallback(Datum arg, Oid relid)
24242358
typentry->flags &= ~TCFLAGS_OPERATOR_FLAGS;
24252359
}
24262360
}
2427-
else
2428-
{
2429-
HASH_SEQ_STATUSstatus;
2430-
2431-
/*
2432-
* Relid is invalid. By convention we need to reset all composite
2433-
* types in cache. Also, we should reset flags for domain types, and
2434-
* we loop over all entries in hash, so, do it in a single scan.
2435-
*/
2436-
hash_seq_init(&status,TypeCacheHash);
2437-
while ((typentry= (TypeCacheEntry*)hash_seq_search(&status))!=NULL)
2438-
{
2439-
if (typentry->typtype==TYPTYPE_COMPOSITE)
2440-
{
2441-
InvalidateCompositeTypeCacheEntry(typentry);
2442-
}
2443-
elseif (typentry->typtype==TYPTYPE_DOMAIN)
2444-
{
2445-
/*
2446-
* If it's domain over composite, reset flags. (We don't
2447-
* bother trying to determine whether the specific base type
2448-
* needs a reset.) Note that if we haven't determined whether
2449-
* the base type is composite, we don't need to reset
2450-
* anything.
2451-
*/
2452-
if (typentry->flags&TCFLAGS_DOMAIN_BASE_IS_COMPOSITE)
2453-
typentry->flags &= ~TCFLAGS_OPERATOR_FLAGS;
2454-
}
2455-
}
2456-
}
24572361
}
24582362

24592363
/*
@@ -2484,8 +2388,6 @@ TypeCacheTypCallback(Datum arg, int cacheid, uint32 hashvalue)
24842388

24852389
while ((typentry= (TypeCacheEntry*)hash_seq_search(&status))!=NULL)
24862390
{
2487-
boolhadPgTypeData= (typentry->flags&TCFLAGS_HAVE_PG_TYPE_DATA);
2488-
24892391
Assert(hashvalue==0||typentry->type_id_hash==hashvalue);
24902392

24912393
/*
@@ -2495,13 +2397,6 @@ TypeCacheTypCallback(Datum arg, int cacheid, uint32 hashvalue)
24952397
*/
24962398
typentry->flags &= ~(TCFLAGS_HAVE_PG_TYPE_DATA |
24972399
TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS);
2498-
2499-
/*
2500-
* Call check_delete_rel_type_cache() if we cleaned
2501-
* TCFLAGS_HAVE_PG_TYPE_DATA flag previously.
2502-
*/
2503-
if (hadPgTypeData)
2504-
delete_rel_type_cache_if_needed(typentry);
25052400
}
25062401
}
25072402

@@ -3010,85 +2905,3 @@ shared_record_typmod_registry_detach(dsm_segment *segment, Datum datum)
30102905
}
30112906
CurrentSession->shared_typmod_registry=NULL;
30122907
}
3013-
3014-
/*
3015-
* Insert RelIdToTypeIdCacheHash entry after setting of the
3016-
* TCFLAGS_HAVE_PG_TYPE_DATA flag if needed.
3017-
*/
3018-
staticvoid
3019-
insert_rel_type_cache_if_needed(TypeCacheEntry*typentry)
3020-
{
3021-
Assert(typentry->flags&TCFLAGS_HAVE_PG_TYPE_DATA);
3022-
3023-
/* Immediately quit for non-composite types */
3024-
if (typentry->typtype!=TYPTYPE_COMPOSITE)
3025-
return;
3026-
3027-
/* typrelid should be given for composite types */
3028-
Assert(OidIsValid(typentry->typrelid));
3029-
3030-
/*
3031-
* Insert a RelIdToTypeIdCacheHash entry if the typentry doesn't have any
3032-
* information indicating there should be such an entry already.
3033-
*/
3034-
if (!(typentry->flags&TCFLAGS_OPERATOR_FLAGS)&&
3035-
typentry->tupDesc==NULL)
3036-
{
3037-
RelIdToTypeIdCacheEntry*relentry;
3038-
boolfound;
3039-
3040-
relentry= (RelIdToTypeIdCacheEntry*)hash_search(RelIdToTypeIdCacheHash,
3041-
&typentry->typrelid,
3042-
HASH_ENTER,&found);
3043-
Assert(!found);
3044-
relentry->relid=typentry->typrelid;
3045-
relentry->composite_typid=typentry->type_id;
3046-
}
3047-
}
3048-
3049-
/*
3050-
* Delete entry RelIdToTypeIdCacheHash if needed after resetting of the
3051-
* TCFLAGS_HAVE_PG_TYPE_DATA flag, or any of TCFLAGS_OPERATOR_FLAGS flags,
3052-
* or tupDesc.
3053-
*/
3054-
staticvoid
3055-
delete_rel_type_cache_if_needed(TypeCacheEntry*typentry)
3056-
{
3057-
/* Immediately quit for non-composite types */
3058-
if (typentry->typtype!=TYPTYPE_COMPOSITE)
3059-
return;
3060-
3061-
/* typrelid should be given for composite types */
3062-
Assert(OidIsValid(typentry->typrelid));
3063-
3064-
/*
3065-
* Delete a RelIdToTypeIdCacheHash entry if the typentry doesn't have any
3066-
* information indicating entry should be still there.
3067-
*/
3068-
if (!(typentry->flags&TCFLAGS_HAVE_PG_TYPE_DATA)&&
3069-
!(typentry->flags&TCFLAGS_OPERATOR_FLAGS)&&
3070-
typentry->tupDesc==NULL)
3071-
{
3072-
boolfound;
3073-
3074-
(void)hash_search(RelIdToTypeIdCacheHash,
3075-
&typentry->typrelid,
3076-
HASH_REMOVE,&found);
3077-
Assert(found);
3078-
}
3079-
else
3080-
{
3081-
#ifdefUSE_ASSERT_CHECKING
3082-
/*
3083-
* In assert-enabled builds otherwise check for RelIdToTypeIdCacheHash
3084-
* entry if it should exist.
3085-
*/
3086-
boolfound;
3087-
3088-
(void)hash_search(RelIdToTypeIdCacheHash,
3089-
&typentry->typrelid,
3090-
HASH_FIND,&found);
3091-
Assert(found);
3092-
#endif
3093-
}
3094-
}

‎src/tools/pgindent/typedefs.list

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2377,7 +2377,6 @@ RelFileLocator
23772377
RelFileLocatorBackend
23782378
RelFileNumber
23792379
RelIdCacheEnt
2380-
RelIdToTypeIdCacheEntry
23812380
RelInfo
23822381
RelInfoArr
23832382
RelMapFile

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp