77
77
/* The main type cache hashtable searched by lookup_type_cache */
78
78
static HTAB * TypeCacheHash = NULL ;
79
79
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
- static HTAB * RelIdToTypeIdCacheHash = NULL ;
87
-
88
- typedef struct RelIdToTypeIdCacheEntry
89
- {
90
- Oid relid ; /* OID of the relation */
91
- Oid composite_typid ; /* OID of the relation's composite type */
92
- } RelIdToTypeIdCacheEntry ;
93
-
94
80
/* List of type cache entries for domain types */
95
81
static TypeCacheEntry * firstDomainTypeEntry = NULL ;
96
82
@@ -343,8 +329,6 @@ static void shared_record_typmod_registry_detach(dsm_segment *segment,
343
329
static TupleDesc find_or_make_matching_shared_tupledesc (TupleDesc tupdesc );
344
330
static dsa_pointer share_tupledesc (dsa_area * area , TupleDesc tupdesc ,
345
331
uint32 typmod );
346
- static void insert_rel_type_cache_if_needed (TypeCacheEntry * typentry );
347
- static void delete_rel_type_cache_if_needed (TypeCacheEntry * typentry );
348
332
349
333
350
334
/*
@@ -392,13 +376,6 @@ lookup_type_cache(Oid type_id, int flags)
392
376
TypeCacheHash = hash_create ("Type information cache" , 64 ,
393
377
& ctl , HASH_ELEM | HASH_FUNCTION );
394
378
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
-
402
379
/* Also set up callbacks for SI invalidations */
403
380
CacheRegisterRelcacheCallback (TypeCacheRelCallback , (Datum ) 0 );
404
381
CacheRegisterSyscacheCallback (TYPEOID , TypeCacheTypCallback , (Datum ) 0 );
@@ -410,8 +387,6 @@ lookup_type_cache(Oid type_id, int flags)
410
387
CreateCacheMemoryContext ();
411
388
}
412
389
413
- Assert (TypeCacheHash != NULL && RelIdToTypeIdCacheHash != NULL );
414
-
415
390
/* Try to look up an existing entry */
416
391
typentry = (TypeCacheEntry * ) hash_search (TypeCacheHash ,
417
392
& type_id ,
@@ -463,7 +438,6 @@ lookup_type_cache(Oid type_id, int flags)
463
438
typentry -> typelem = typtup -> typelem ;
464
439
typentry -> typcollation = typtup -> typcollation ;
465
440
typentry -> flags |= TCFLAGS_HAVE_PG_TYPE_DATA ;
466
- insert_rel_type_cache_if_needed (typentry );
467
441
468
442
/* If it's a domain, immediately thread it into the domain cache list */
469
443
if (typentry -> typtype == TYPTYPE_DOMAIN )
@@ -509,7 +483,6 @@ lookup_type_cache(Oid type_id, int flags)
509
483
typentry -> typelem = typtup -> typelem ;
510
484
typentry -> typcollation = typtup -> typcollation ;
511
485
typentry -> flags |= TCFLAGS_HAVE_PG_TYPE_DATA ;
512
- insert_rel_type_cache_if_needed (typentry );
513
486
514
487
ReleaseSysCache (tp );
515
488
}
@@ -2308,53 +2281,6 @@ SharedRecordTypmodRegistryAttach(SharedRecordTypmodRegistry *registry)
2308
2281
CurrentSession -> shared_typmod_table = typmod_table ;
2309
2282
}
2310
2283
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
- static void
2320
- InvalidateCompositeTypeCacheEntry (TypeCacheEntry * typentry )
2321
- {
2322
- bool hadTupDescOrOpclass ;
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
-
2358
2284
/*
2359
2285
* TypeCacheRelCallback
2360
2286
* Relcache inval callback function
@@ -2364,55 +2290,63 @@ InvalidateCompositeTypeCacheEntry(TypeCacheEntry *typentry)
2364
2290
* whatever info we have cached about the composite type's comparability.
2365
2291
*
2366
2292
* 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.
2370
2305
*/
2371
2306
static void
2372
2307
TypeCacheRelCallback (Datum arg , Oid relid )
2373
2308
{
2309
+ HASH_SEQ_STATUS status ;
2374
2310
TypeCacheEntry * typentry ;
2375
2311
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 )
2381
2315
{
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 )
2393
2317
{
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 ;
2397
2321
2398
- if (typentry != NULL )
2322
+ /* Delete tupdesc if we have it */
2323
+ if (typentry -> tupDesc != NULL )
2399
2324
{
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 ;
2402
2334
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 ;
2404
2344
}
2405
- }
2406
2345
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
+ else if (typentry -> typtype == TYPTYPE_DOMAIN )
2416
2350
{
2417
2351
/*
2418
2352
* If it's domain over composite, reset flags. (We don't bother
@@ -2424,36 +2358,6 @@ TypeCacheRelCallback(Datum arg, Oid relid)
2424
2358
typentry -> flags &= ~TCFLAGS_OPERATOR_FLAGS ;
2425
2359
}
2426
2360
}
2427
- else
2428
- {
2429
- HASH_SEQ_STATUS status ;
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
- else if (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
- }
2457
2361
}
2458
2362
2459
2363
/*
@@ -2484,8 +2388,6 @@ TypeCacheTypCallback(Datum arg, int cacheid, uint32 hashvalue)
2484
2388
2485
2389
while ((typentry = (TypeCacheEntry * ) hash_seq_search (& status )) != NULL )
2486
2390
{
2487
- bool hadPgTypeData = (typentry -> flags & TCFLAGS_HAVE_PG_TYPE_DATA );
2488
-
2489
2391
Assert (hashvalue == 0 || typentry -> type_id_hash == hashvalue );
2490
2392
2491
2393
/*
@@ -2495,13 +2397,6 @@ TypeCacheTypCallback(Datum arg, int cacheid, uint32 hashvalue)
2495
2397
*/
2496
2398
typentry -> flags &= ~(TCFLAGS_HAVE_PG_TYPE_DATA |
2497
2399
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 );
2505
2400
}
2506
2401
}
2507
2402
@@ -3010,85 +2905,3 @@ shared_record_typmod_registry_detach(dsm_segment *segment, Datum datum)
3010
2905
}
3011
2906
CurrentSession -> shared_typmod_registry = NULL ;
3012
2907
}
3013
-
3014
- /*
3015
- * Insert RelIdToTypeIdCacheHash entry after setting of the
3016
- * TCFLAGS_HAVE_PG_TYPE_DATA flag if needed.
3017
- */
3018
- static void
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
- bool found ;
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
- static void
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
- bool found ;
3073
-
3074
- (void ) hash_search (RelIdToTypeIdCacheHash ,
3075
- & typentry -> typrelid ,
3076
- HASH_REMOVE , & found );
3077
- Assert (found );
3078
- }
3079
- else
3080
- {
3081
- #ifdef USE_ASSERT_CHECKING
3082
- /*
3083
- * In assert-enabled builds otherwise check for RelIdToTypeIdCacheHash
3084
- * entry if it should exist.
3085
- */
3086
- bool found ;
3087
-
3088
- (void ) hash_search (RelIdToTypeIdCacheHash ,
3089
- & typentry -> typrelid ,
3090
- HASH_FIND , & found );
3091
- Assert (found );
3092
- #endif
3093
- }
3094
- }
0 commit comments