@@ -185,6 +185,9 @@ typedef struct RelationSyncEntry
185
185
* row filter expressions, column list, etc.
186
186
*/
187
187
MemoryContext entry_cxt ;
188
+
189
+ /* Hash value of schema OID. Used for pg_namespace syscache callback */
190
+ uint32 schema_hashvalue ;
188
191
} RelationSyncEntry ;
189
192
190
193
/*
@@ -227,8 +230,7 @@ static void send_relation_and_attrs(Relation relation, TransactionId xid,
227
230
LogicalDecodingContext * ctx ,
228
231
RelationSyncEntry * relentry );
229
232
static void rel_sync_cache_relation_cb (Datum arg , Oid relid );
230
- static void rel_sync_cache_publication_cb (Datum arg , int cacheid ,
231
- uint32 hashvalue );
233
+ static void rel_sync_cache_schema_cb (Datum arg , int cacheid , uint32 hashvalue );
232
234
static void set_schema_sent_in_streamed_txn (RelationSyncEntry * entry ,
233
235
TransactionId xid );
234
236
static bool get_schema_sent_in_streamed_txn (RelationSyncEntry * entry ,
@@ -1974,18 +1976,11 @@ init_rel_sync_cache(MemoryContext cachectx)
1974
1976
CacheRegisterRelcacheCallback (rel_sync_cache_relation_cb , (Datum ) 0 );
1975
1977
1976
1978
/*
1977
- * Flush all cache entries after a pg_namespace change, in case it was a
1979
+ * Flush related entries after a pg_namespace change, in case it was a
1978
1980
* schema rename affecting a relation being replicated.
1979
- *
1980
- * XXX: It is not a good idea to invalidate all the relation entries in
1981
- * RelationSyncCache on schema rename. We can optimize it to invalidate
1982
- * only the required relations by either having a specific invalidation
1983
- * message containing impacted relations or by having schema information
1984
- * in each RelationSyncCache entry and using hashvalue of pg_namespace.oid
1985
- * passed to the callback.
1986
1981
*/
1987
1982
CacheRegisterSyscacheCallback (NAMESPACEOID ,
1988
- rel_sync_cache_publication_cb ,
1983
+ rel_sync_cache_schema_cb ,
1989
1984
(Datum ) 0 );
1990
1985
1991
1986
relation_callbacks_registered = true;
@@ -2057,6 +2052,7 @@ get_rel_sync_entry(PGOutputData *data, Relation relation)
2057
2052
entry -> publish_as_relid = InvalidOid ;
2058
2053
entry -> columns = NULL ;
2059
2054
entry -> attrmap = NULL ;
2055
+ entry -> schema_hashvalue = 0 ;
2060
2056
}
2061
2057
2062
2058
/* Validate the entry */
@@ -2303,6 +2299,10 @@ get_rel_sync_entry(PGOutputData *data, Relation relation)
2303
2299
list_free (schemaPubids );
2304
2300
list_free (rel_publications );
2305
2301
2302
+ entry -> schema_hashvalue =
2303
+ GetSysCacheHashValue1 (NAMESPACEOID ,
2304
+ ObjectIdGetDatum (RelationGetNamespace (relation )));
2305
+
2306
2306
entry -> replicate_valid = true;
2307
2307
}
2308
2308
@@ -2401,12 +2401,12 @@ rel_sync_cache_relation_cb(Datum arg, Oid relid)
2401
2401
}
2402
2402
2403
2403
/*
2404
- * Publication relation/ schema map syscache invalidation callback
2404
+ * schema syscache invalidation callback
2405
2405
*
2406
2406
* Called for invalidations on pg_namespace.
2407
2407
*/
2408
- static void
2409
- rel_sync_cache_publication_cb (Datum arg , int cacheid , uint32 hashvalue )
2408
+ void
2409
+ rel_sync_cache_schema_cb (Datum arg , int cacheid , uint32 hashvalue )
2410
2410
{
2411
2411
HASH_SEQ_STATUS status ;
2412
2412
RelationSyncEntry * entry ;
@@ -2420,13 +2420,15 @@ rel_sync_cache_publication_cb(Datum arg, int cacheid, uint32 hashvalue)
2420
2420
return ;
2421
2421
2422
2422
/*
2423
- * We have no easy way to identify which cache entries this invalidation
2424
- * event might have affected, so just mark them all invalid .
2423
+ * Identify entries which belongs to the specified schema, and invalidate
2424
+ * it .
2425
2425
*/
2426
2426
hash_seq_init (& status , RelationSyncCache );
2427
2427
while ((entry = (RelationSyncEntry * ) hash_seq_search (& status )) != NULL )
2428
2428
{
2429
- entry -> replicate_valid = false;
2429
+ /* hashvalue == 0 means a cache reset, must clear all state */
2430
+ if (hashvalue == 0 || entry -> schema_hashvalue == hashvalue )
2431
+ entry -> replicate_valid = false;
2430
2432
}
2431
2433
}
2432
2434
0 commit comments