diff options
Diffstat (limited to 'src/backend/replication/logical/relation.c')
-rw-r--r-- | src/backend/replication/logical/relation.c | 91 |
1 files changed, 61 insertions, 30 deletions
diff --git a/src/backend/replication/logical/relation.c b/src/backend/replication/logical/relation.c index f5a0ef2bd9d..b355f32f03c 100644 --- a/src/backend/replication/logical/relation.c +++ b/src/backend/replication/logical/relation.c @@ -220,41 +220,63 @@ logicalrep_rel_att_by_name(LogicalRepRelation *remoterel, const char *attname) } /* - * Report error with names of the missing local relation column(s), if any. + * Returns a comma-separated string of attribute names based on the provided + * relation and bitmap indicating which attributes to include. */ -static void -logicalrep_report_missing_attrs(LogicalRepRelation *remoterel, - Bitmapset *missingatts) +static char * +logicalrep_get_attrs_str(LogicalRepRelation *remoterel, Bitmapset *atts) { - if (!bms_is_empty(missingatts)) + StringInfoData attsbuf; + int attcnt = 0; + int i = -1; + + Assert(!bms_is_empty(atts)); + + initStringInfo(&attsbuf); + + while ((i = bms_next_member(atts, i)) >= 0) { - StringInfoData missingattsbuf; - int missingattcnt = 0; - int i; + attcnt++; + if (attcnt > 1) + appendStringInfo(&attsbuf, _(", ")); - initStringInfo(&missingattsbuf); + appendStringInfo(&attsbuf, _("\"%s\""), remoterel->attnames[i]); + } - i = -1; - while ((i = bms_next_member(missingatts, i)) >= 0) - { - missingattcnt++; - if (missingattcnt == 1) - appendStringInfo(&missingattsbuf, _("\"%s\""), - remoterel->attnames[i]); - else - appendStringInfo(&missingattsbuf, _(", \"%s\""), - remoterel->attnames[i]); - } + return attsbuf.data; +} +/* + * If attempting to replicate missing or generated columns, report an error. + * Prioritize 'missing' errors if both occur though the prioritization is + * arbitrary. + */ +static void +logicalrep_report_missing_or_gen_attrs(LogicalRepRelation *remoterel, + Bitmapset *missingatts, + Bitmapset *generatedatts) +{ + if (!bms_is_empty(missingatts)) ereport(ERROR, - (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg_plural("logical replication target relation \"%s.%s\" is missing replicated column: %s", - "logical replication target relation \"%s.%s\" is missing replicated columns: %s", - missingattcnt, - remoterel->nspname, - remoterel->relname, - missingattsbuf.data))); - } + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg_plural("logical replication target relation \"%s.%s\" is missing replicated column: %s", + "logical replication target relation \"%s.%s\" is missing replicated columns: %s", + bms_num_members(missingatts), + remoterel->nspname, + remoterel->relname, + logicalrep_get_attrs_str(remoterel, + missingatts))); + + if (!bms_is_empty(generatedatts)) + ereport(ERROR, + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg_plural("logical replication target relation \"%s.%s\" has incompatible generated column: %s", + "logical replication target relation \"%s.%s\" has incompatible generated columns: %s", + bms_num_members(generatedatts), + remoterel->nspname, + remoterel->relname, + logicalrep_get_attrs_str(remoterel, + generatedatts))); } /* @@ -380,6 +402,7 @@ logicalrep_rel_open(LogicalRepRelId remoteid, LOCKMODE lockmode) MemoryContext oldctx; int i; Bitmapset *missingatts; + Bitmapset *generatedattrs = NULL; /* Release the no-longer-useful attrmap, if any. */ if (entry->attrmap) @@ -421,7 +444,7 @@ logicalrep_rel_open(LogicalRepRelId remoteid, LOCKMODE lockmode) int attnum; Form_pg_attribute attr = TupleDescAttr(desc, i); - if (attr->attisdropped || attr->attgenerated) + if (attr->attisdropped) { entry->attrmap->attnums[i] = -1; continue; @@ -432,12 +455,20 @@ logicalrep_rel_open(LogicalRepRelId remoteid, LOCKMODE lockmode) entry->attrmap->attnums[i] = attnum; if (attnum >= 0) + { + /* Remember which subscriber columns are generated. */ + if (attr->attgenerated) + generatedattrs = bms_add_member(generatedattrs, attnum); + missingatts = bms_del_member(missingatts, attnum); + } } - logicalrep_report_missing_attrs(remoterel, missingatts); + logicalrep_report_missing_or_gen_attrs(remoterel, missingatts, + generatedattrs); /* be tidy */ + bms_free(generatedattrs); bms_free(missingatts); /* |