diff options
Diffstat (limited to 'src/backend/catalog/pg_subscription.c')
-rw-r--r-- | src/backend/catalog/pg_subscription.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/src/backend/catalog/pg_subscription.c b/src/backend/catalog/pg_subscription.c index 44cb285b686..c32fc8137d8 100644 --- a/src/backend/catalog/pg_subscription.c +++ b/src/backend/catalog/pg_subscription.c @@ -29,6 +29,7 @@ #include "utils/array.h" #include "utils/builtins.h" #include "utils/fmgroids.h" +#include "utils/lsyscache.h" #include "utils/pg_lsn.h" #include "utils/rel.h" #include "utils/syscache.h" @@ -337,6 +338,13 @@ GetSubscriptionRelState(Oid subid, Oid relid, XLogRecPtr *sublsn) char substate; bool isnull; Datum d; + Relation rel; + + /* + * This is to avoid the race condition with AlterSubscription which tries + * to remove this relstate. + */ + rel = table_open(SubscriptionRelRelationId, AccessShareLock); /* Try finding the mapping. */ tup = SearchSysCache2(SUBSCRIPTIONRELMAP, @@ -363,6 +371,8 @@ GetSubscriptionRelState(Oid subid, Oid relid, XLogRecPtr *sublsn) /* Cleanup */ ReleaseSysCache(tup); + table_close(rel, AccessShareLock); + return substate; } @@ -403,6 +413,34 @@ RemoveSubscriptionRel(Oid subid, Oid relid) scan = table_beginscan_catalog(rel, nkeys, skey); while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection))) { + Form_pg_subscription_rel subrel; + + subrel = (Form_pg_subscription_rel) GETSTRUCT(tup); + + /* + * We don't allow to drop the relation mapping when the table + * synchronization is in progress unless the caller updates the + * corresponding subscription as well. This is to ensure that we don't + * leave tablesync slots or origins in the system when the + * corresponding table is dropped. + */ + if (!OidIsValid(subid) && subrel->srsubstate != SUBREL_STATE_READY) + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("could not drop relation mapping for subscription \"%s\"", + get_subscription_name(subrel->srsubid, false)), + errdetail("Table synchronization for relation \"%s\" is in progress and is in state \"%c\".", + get_rel_name(relid), subrel->srsubstate), + /* + * translator: first %s is a SQL ALTER command and second %s is a + * SQL DROP command + */ + errhint("Use %s to enable subscription if not already enabled or use %s to drop the subscription.", + "ALTER SUBSCRIPTION ... ENABLE", + "DROP SUBSCRIPTION ..."))); + } + CatalogTupleDelete(rel, &tup->t_self); } table_endscan(scan); |