diff --git a/doc/src/sgml/ref/alter_subscription.sgml b/doc/src/sgml/ref/alter_subscription.sgml index bead996..5f4d40a 100644 --- a/doc/src/sgml/ref/alter_subscription.sgml +++ b/doc/src/sgml/ref/alter_subscription.sgml @@ -48,6 +48,13 @@ ALTER SUBSCRIPTION name RENAME TO < (Currently, all subscription owners must be superusers, so the owner checks will be bypassed in practice. But this might change in the future.) + + + ALTER SUBSCRIPTION ... SET PUBLCIATION with + refresh option and + ALTER SUBSCRIPTION ... REFRESH PUBLICATION cannot be + executed inside a transaction block. + diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c index 5aae7b6..6f3f4a6 100644 --- a/src/backend/commands/subscriptioncmds.c +++ b/src/backend/commands/subscriptioncmds.c @@ -612,7 +612,7 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data) * Alter the existing subscription. */ ObjectAddress -AlterSubscription(AlterSubscriptionStmt *stmt) +AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel) { Relation rel; ObjectAddress myself; @@ -743,6 +743,15 @@ AlterSubscription(AlterSubscriptionStmt *stmt) /* Refresh if user asked us to. */ if (refresh) { + /* + * Since stopping table sync worker is not transactional, the table + * sync worker is stopped even if the transaction rolls back. So we + * cannot run ALTER SUBSCRIPTION SET PUBLICATION with refresh option + * and ALTER SUBSCRIPTION REFRESH PUBLICATION (see below) inside a + * transaction block if refresh option is specified. + */ + PreventTransactionChain(isTopLevel, "ALTER SUBSCRIPTION ... SET PUBLICATION ... WITH (refresh = true)"); + if (!sub->enabled) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), @@ -762,6 +771,12 @@ AlterSubscription(AlterSubscriptionStmt *stmt) { bool copy_data; + /* + * As same resason as above description at ALTER_SUBSCRIPTION_PUBLICATION, + * we cannot run this command inside a transaction block + */ + PreventTransactionChain(isTopLevel, "ALTER SUBSCRIPTION ... REFRESH PUBLICATION"); + if (!sub->enabled) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index a22fd53..db4e192 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -1626,7 +1626,7 @@ ProcessUtilitySlow(ParseState *pstate, break; case T_AlterSubscriptionStmt: - address = AlterSubscription((AlterSubscriptionStmt *) parsetree); + address = AlterSubscription((AlterSubscriptionStmt *) parsetree, isTopLevel); break; case T_DropSubscriptionStmt: diff --git a/src/include/commands/subscriptioncmds.h b/src/include/commands/subscriptioncmds.h index 1e4428e..f5a9e28 100644 --- a/src/include/commands/subscriptioncmds.h +++ b/src/include/commands/subscriptioncmds.h @@ -20,7 +20,7 @@ extern ObjectAddress CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel); -extern ObjectAddress AlterSubscription(AlterSubscriptionStmt *stmt); +extern ObjectAddress AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel); extern void DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel); extern ObjectAddress AlterSubscriptionOwner(const char *name, Oid newOwnerId); diff --git a/src/test/regress/expected/subscription.out b/src/test/regress/expected/subscription.out index 4fcbf7e..6cc33a1 100644 --- a/src/test/regress/expected/subscription.out +++ b/src/test/regress/expected/subscription.out @@ -141,6 +141,16 @@ HINT: The owner of a subscription must be a superuser. ALTER ROLE regress_subscription_user2 SUPERUSER; -- now it works ALTER SUBSCRIPTION testsub OWNER TO regress_subscription_user2; +-- fail - cannot do ALTER SUBSCRIPTION ... SET PUBLICATION inside transaction block with refreshing +BEGIN; +ALTER SUBSCRIPTION testsub SET PUBLICATION testpub WITH (refresh = true); +ERROR: ALTER SUBSCRIPTION ... SET PUBLICATION ... WITH (refresh = true) cannot run inside a transaction block +COMMIT; +-- fail - cannot do ALTER SUBSCRIPTION ... REFRESH PUBLICATION inside transaction block +BEGIN; +ALTER SUBSCRIPTION testsub REFRESH PUBLICATION; +ERROR: ALTER SUBSCRIPTION ... REFRESH PUBLICATION cannot run inside a transaction block +COMMIT; -- fail - cannot do DROP SUBSCRIPTION inside transaction block with slot name BEGIN; DROP SUBSCRIPTION testsub; diff --git a/src/test/regress/sql/subscription.sql b/src/test/regress/sql/subscription.sql index 36fa1bb..aa14cae 100644 --- a/src/test/regress/sql/subscription.sql +++ b/src/test/regress/sql/subscription.sql @@ -102,6 +102,16 @@ ALTER ROLE regress_subscription_user2 SUPERUSER; -- now it works ALTER SUBSCRIPTION testsub OWNER TO regress_subscription_user2; +-- fail - cannot do ALTER SUBSCRIPTION ... SET PUBLICATION inside transaction block with refreshing +BEGIN; +ALTER SUBSCRIPTION testsub SET PUBLICATION testpub WITH (refresh = true); +COMMIT; + +-- fail - cannot do ALTER SUBSCRIPTION ... REFRESH PUBLICATION inside transaction block +BEGIN; +ALTER SUBSCRIPTION testsub REFRESH PUBLICATION; +COMMIT; + -- fail - cannot do DROP SUBSCRIPTION inside transaction block with slot name BEGIN; DROP SUBSCRIPTION testsub;