aboutsummaryrefslogtreecommitdiff
path: root/src/backend/catalog/pg_subscription.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/catalog/pg_subscription.c')
-rw-r--r--src/backend/catalog/pg_subscription.c38
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);