From e5372b48b94f17dcce5d8f3b26d55b0f182e4306 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 20 Jul 2020 14:55:56 -0400 Subject: [PATCH] Correctly mark pg_subscription_rel.srsublsn as nullable. The code has always set this column to NULL when it's not valid, but the catalog header's description failed to reflect that, as did the SGML docs, as did some of the code. To prevent future coding errors of the same ilk, let's hide the field from C code as though it were variable-length (which, in a sense, it is). As with commit 72eab84a5, we can only fix this cleanly in HEAD and v13; the problem extends further back but we'll need some klugery in the released branches. Discussion: https://postgr.es/m/367660.1595202498@sss.pgh.pa.us --- doc/src/sgml/catalogs.sgml | 4 +++- src/backend/catalog/pg_subscription.c | 18 ++++++++++++++++-- src/include/catalog/catversion.h | 2 +- src/include/catalog/pg_subscription_rel.h | 14 ++++++++++++-- 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index 918b58242f..a15d76a0e9 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -7620,7 +7620,9 @@ SCRAM-SHA-256$<iteration count>:&l srsublsn pg_lsn - End LSN for s and r states. + Remote LSN of the state change used for synchronization coordination + when in s or r states, + otherwise null diff --git a/src/backend/catalog/pg_subscription.c b/src/backend/catalog/pg_subscription.c index cb15731115..0d23b20d62 100644 --- a/src/backend/catalog/pg_subscription.c +++ b/src/backend/catalog/pg_subscription.c @@ -451,13 +451,20 @@ GetSubscriptionRelations(Oid subid) { Form_pg_subscription_rel subrel; SubscriptionRelState *relstate; + Datum d; + bool isnull; subrel = (Form_pg_subscription_rel) GETSTRUCT(tup); relstate = (SubscriptionRelState *) palloc(sizeof(SubscriptionRelState)); relstate->relid = subrel->srrelid; relstate->state = subrel->srsubstate; - relstate->lsn = subrel->srsublsn; + d = SysCacheGetAttr(SUBSCRIPTIONRELMAP, tup, + Anum_pg_subscription_rel_srsublsn, &isnull); + if (isnull) + relstate->lsn = InvalidXLogRecPtr; + else + relstate->lsn = DatumGetLSN(d); res = lappend(res, relstate); } @@ -503,13 +510,20 @@ GetSubscriptionNotReadyRelations(Oid subid) { Form_pg_subscription_rel subrel; SubscriptionRelState *relstate; + Datum d; + bool isnull; subrel = (Form_pg_subscription_rel) GETSTRUCT(tup); relstate = (SubscriptionRelState *) palloc(sizeof(SubscriptionRelState)); relstate->relid = subrel->srrelid; relstate->state = subrel->srsubstate; - relstate->lsn = subrel->srsublsn; + d = SysCacheGetAttr(SUBSCRIPTIONRELMAP, tup, + Anum_pg_subscription_rel_srsublsn, &isnull); + if (isnull) + relstate->lsn = InvalidXLogRecPtr; + else + relstate->lsn = DatumGetLSN(d); res = lappend(res, relstate); } diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 9d9334272e..282019c49d 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 202007191 +#define CATALOG_VERSION_NO 202007201 #endif diff --git a/src/include/catalog/pg_subscription_rel.h b/src/include/catalog/pg_subscription_rel.h index c44df04c72..f384f4e7fa 100644 --- a/src/include/catalog/pg_subscription_rel.h +++ b/src/include/catalog/pg_subscription_rel.h @@ -33,8 +33,18 @@ CATALOG(pg_subscription_rel,6102,SubscriptionRelRelationId) Oid srsubid; /* Oid of subscription */ Oid srrelid; /* Oid of relation */ char srsubstate; /* state of the relation in subscription */ - XLogRecPtr srsublsn; /* remote lsn of the state change used for - * synchronization coordination */ + + /* + * Although srsublsn is a fixed-width type, it is allowed to be NULL, so + * we prevent direct C code access to it just as for a varlena field. + */ +#ifdef CATALOG_VARLEN /* variable-length fields start here */ + + XLogRecPtr srsublsn BKI_FORCE_NULL; /* remote LSN of the state change + * used for synchronization + * coordination, or NULL if not + * valid */ +#endif } FormData_pg_subscription_rel; typedef FormData_pg_subscription_rel *Form_pg_subscription_rel;