v1_amit_1.patch.txt
text/plain
Filename: v1_amit_1.patch.txt
Type: text/plain
Part: 0
Message:
Re: Logical Replication of sequences
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 73b068dd31c..267b898dca1 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -113,18 +113,18 @@ typedef struct PublicationRelKind
} PublicationRelKind;
static List *fetch_relation_list(WalReceiverConn *wrconn, List *publications);
-static void check_publications_origin_sequences(WalReceiverConn *wrconn,
- List *publications,
- char *origin,
- Oid *subrel_local_oids,
- int subrel_count,
- char *subname);
static void check_publications_origin_tables(WalReceiverConn *wrconn,
List *publications, bool copydata,
bool retain_dead_tuples,
char *origin,
Oid *subrel_local_oids,
int subrel_count, char *subname);
+static void check_publications_origin_sequences(WalReceiverConn* wrconn,
+ List *publications,
+ char *origin,
+ Oid *subrel_local_oids,
+ int subrel_count,
+ char *subname);
static void check_pub_dead_tuple_retention(WalReceiverConn *wrconn);
static void check_duplicates_in_publist(List *publist, Datum *datums);
static List *merge_publications(List *oldpublist, List *newpublist, bool addpub, const char *subname);
@@ -979,9 +979,8 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data,
else
subrel_local_oids[tbl_count++] = relstate->relid;
}
- qsort(subrel_local_oids, tbl_count,
- sizeof(Oid), oid_cmp);
+ qsort(subrel_local_oids, tbl_count, sizeof(Oid), oid_cmp);
check_publications_origin_tables(wrconn, sub->publications, copy_data,
sub->retaindeadtuples, sub->origin,
subrel_local_oids, tbl_count,
@@ -2461,106 +2460,6 @@ AlterSubscriptionOwner_oid(Oid subid, Oid newOwnerId)
table_close(rel, RowExclusiveLock);
}
-static void
-check_publications_origin_sequences(WalReceiverConn *wrconn, List *publications,
- char *origin, Oid *subrel_local_oids,
- int subrel_count, char *subname)
-{
- WalRcvExecResult *res;
- StringInfoData cmd;
- TupleTableSlot *slot;
- int i;
- Oid tableRow[1] = {TEXTOID};
- List *publist = NIL;
-
- /* Enable sequence synchronization checks only when origin is 'none' */
- if (!origin || pg_strcasecmp(origin, LOGICALREP_ORIGIN_NONE) != 0)
- return;
-
- initStringInfo(&cmd);
- appendStringInfoString(&cmd,
- "SELECT DISTINCT P.pubname AS pubname\n"
- "FROM pg_publication P,\n"
- " LATERAL pg_get_publication_sequences(P.pubname) GPR\n"
- " JOIN pg_subscription_rel PS ON (GPR.relid = PS.srrelid),\n"
- " pg_class C JOIN pg_namespace N ON (N.oid = C.relnamespace)\n"
- "WHERE C.oid = GPR.relid "
- " AND P.pubname IN (");
-
- GetPublicationsStr(publications, &cmd, true);
- appendStringInfoString(&cmd, ")\n");
-
- /*
- * In case of ALTER SUBSCRIPTION ... REFRESH PUBLICATION,
- * subrel_local_oids contains the list of relations that are already
- * present on the subscriber. This check should be skipped as these will
- * not be re-synced.
- */
- for (i = 0; i < subrel_count; i++)
- {
- Oid relid = subrel_local_oids[i];
- char *schemaname = get_namespace_name(get_rel_namespace(relid));
- char *tablename = get_rel_name(relid);
-
- appendStringInfo(&cmd, "AND NOT (N.nspname = '%s' AND C.relname = '%s')\n",
- schemaname, tablename);
- }
-
- res = walrcv_exec(wrconn, cmd.data, 1, tableRow);
- pfree(cmd.data);
-
- if (res->status != WALRCV_OK_TUPLES)
- ereport(ERROR,
- (errcode(ERRCODE_CONNECTION_FAILURE),
- errmsg("could not receive list of replicated relations from the publisher: %s",
- res->err)));
-
- /* Process relations. */
- slot = MakeSingleTupleTableSlot(res->tupledesc, &TTSOpsMinimalTuple);
- while (tuplestore_gettupleslot(res->tuplestore, true, false, slot))
- {
- char *pubname;
- bool isnull;
-
- pubname = TextDatumGetCString(slot_getattr(slot, 1, &isnull));
- Assert(!isnull);
-
- ExecClearTuple(slot);
- publist = list_append_unique(publist, makeString(pubname));
- }
-
- /*
- * Log a warning if the publisher has subscribed to the same sequence from
- * some other publisher. We cannot know the origin of sequences data during
- * the initial sync.
- */
- if (publist)
- {
- StringInfo pubnames = makeStringInfo();
- StringInfo err_msg = makeStringInfo();
- StringInfo err_hint = makeStringInfo();
-
- /* Prepare the list of publication(s) for warning message. */
- GetPublicationsStr(publist, pubnames, false);
-
- appendStringInfo(err_msg, _("subscription \"%s\" requested copy_data with origin = NONE but might copy data that had a different origin"),
- subname);
- appendStringInfoString(err_hint, _("Verify that initial data copied from the publisher sequences did not come from other origins."));
-
- ereport(WARNING,
- errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg_internal("%s", err_msg->data),
- errdetail_plural("The subscription subscribes to a publication (%s) that contains sequences that are written to by other subscriptions.",
- "The subscription subscribes to publications (%s) that contain sequences that are written to by other subscriptions.",
- list_length(publist), pubnames->data),
- errhint_internal("%s", err_hint->data));
- }
-
- ExecDropSingleTupleTableSlot(slot);
-
- walrcv_clear_result(res);
-}
-
/*
* Check and log a warning if the publisher has subscribed to the same table,
* its partition ancestors (if it's a partition), or its partition children (if
@@ -2726,6 +2625,116 @@ check_publications_origin_tables(WalReceiverConn *wrconn, List *publications,
walrcv_clear_result(res);
}
+/*
+ * This function is similar to check_publications_origin_tables and serves
+ * same purpose for sequences.
+ *
+ * In addition to the checks where check_publications_origin_tables is used,
+ * this function is also used for ALTER SUBSCRIPTION ... REFRESH SEQUENCES.
+ */
+static void
+check_publications_origin_sequences(WalReceiverConn* wrconn, List* publications,
+ char *origin, Oid *subrel_local_oids,
+ int subrel_count, char *subname)
+{
+ WalRcvExecResult *res;
+ StringInfoData cmd;
+ TupleTableSlot *slot;
+ int i;
+ Oid tableRow[1] = { TEXTOID };
+ List *publist = NIL;
+
+ /*
+ * Enable sequence synchronization checks only when origin is 'none', to
+ * ensure that sequence data from other origins is not inadvertently
+ * copied.
+ */
+ if (!origin || pg_strcasecmp(origin, LOGICALREP_ORIGIN_NONE) != 0)
+ return;
+
+ initStringInfo(&cmd);
+ appendStringInfoString(&cmd,
+ "SELECT DISTINCT P.pubname AS pubname\n"
+ "FROM pg_publication P,\n"
+ " LATERAL pg_get_publication_sequences(P.pubname) GPR\n"
+ " JOIN pg_subscription_rel PS ON (GPR.relid = PS.srrelid),\n"
+ " pg_class C JOIN pg_namespace N ON (N.oid = C.relnamespace)\n"
+ "WHERE C.oid = GPR.relid AND P.pubname IN (");
+
+ GetPublicationsStr(publications, &cmd, true);
+ appendStringInfoString(&cmd, ")\n");
+
+ /*
+ * In case of ALTER SUBSCRIPTION ... REFRESH PUBLICATION,
+ * subrel_local_oids contains the list of relations that are already
+ * present on the subscriber. This check should be skipped as these will
+ * not be re-synced.
+ */
+ for (i = 0; i < subrel_count; i++)
+ {
+ Oid relid = subrel_local_oids[i];
+ char *schemaname = get_namespace_name(get_rel_namespace(relid));
+ char *seqname = get_rel_name(relid);
+
+ appendStringInfo(&cmd, "AND NOT (N.nspname = '%s' AND C.relname = '%s')\n",
+ schemaname, seqname);
+ }
+
+ res = walrcv_exec(wrconn, cmd.data, 1, tableRow);
+ pfree(cmd.data);
+
+ if (res->status != WALRCV_OK_TUPLES)
+ ereport(ERROR,
+ (errcode(ERRCODE_CONNECTION_FAILURE),
+ errmsg("could not receive list of replicated relations from the publisher: %s",
+ res->err)));
+
+ /* Process relations. */
+ slot = MakeSingleTupleTableSlot(res->tupledesc, &TTSOpsMinimalTuple);
+ while (tuplestore_gettupleslot(res->tuplestore, true, false, slot))
+ {
+ char* pubname;
+ bool isnull;
+
+ pubname = TextDatumGetCString(slot_getattr(slot, 1, &isnull));
+ Assert(!isnull);
+
+ ExecClearTuple(slot);
+ publist = list_append_unique(publist, makeString(pubname));
+ }
+
+ /*
+ * Log a warning if the publisher has subscribed to the same sequence from
+ * some other publisher. We cannot know the origin of sequences data during
+ * the initial sync.
+ */
+ if (publist)
+ {
+ StringInfo pubnames = makeStringInfo();
+ StringInfo err_msg = makeStringInfo();
+ StringInfo err_hint = makeStringInfo();
+
+ /* Prepare the list of publication(s) for warning message. */
+ GetPublicationsStr(publist, pubnames, false);
+
+ appendStringInfo(err_msg, _("subscription \"%s\" requested copy_data with origin = NONE but might copy data that had a different origin"),
+ subname);
+ appendStringInfoString(err_hint, _("Verify that initial data copied from the publisher sequences did not come from other origins."));
+
+ ereport(WARNING,
+ errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg_internal("%s", err_msg->data),
+ errdetail_plural("The subscription subscribes to a publication (%s) that contains sequences that are written to by other subscriptions.",
+ "The subscription subscribes to publications (%s) that contain sequences that are written to by other subscriptions.",
+ list_length(publist), pubnames->data),
+ errhint_internal("%s", err_hint->data));
+ }
+
+ ExecDropSingleTupleTableSlot(slot);
+
+ walrcv_clear_result(res);
+}
+
/*
* Determine whether the retain_dead_tuples can be enabled based on the
* publisher's status.