diff options
Diffstat (limited to 'src/backend/replication/pgoutput/pgoutput.c')
-rw-r--r-- | src/backend/replication/pgoutput/pgoutput.c | 80 |
1 files changed, 40 insertions, 40 deletions
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c index 42c06af2391..8deae571433 100644 --- a/src/backend/replication/pgoutput/pgoutput.c +++ b/src/backend/replication/pgoutput/pgoutput.c @@ -979,30 +979,31 @@ pgoutput_column_list_init(PGOutputData *data, List *publications, RelationSyncEntry *entry) { ListCell *lc; + bool first = true; + Relation relation = RelationIdGetRelation(entry->publish_as_relid); /* * Find if there are any column lists for this relation. If there are, - * build a bitmap merging all the column lists. - * - * All the given publication-table mappings must be checked. + * build a bitmap using the column lists. * * Multiple publications might have multiple column lists for this * relation. * + * Note that we don't support the case where the column list is different + * for the same table when combining publications. See comments atop + * fetch_table_list. But one can later change the publication so we still + * need to check all the given publication-table mappings and report an + * error if any publications have a different column list. + * * FOR ALL TABLES and FOR ALL TABLES IN SCHEMA implies "don't use column - * list" so it takes precedence. + * list". */ foreach(lc, publications) { Publication *pub = lfirst(lc); HeapTuple cftuple = NULL; Datum cfdatum = 0; - - /* - * Assume there's no column list. Only if we find pg_publication_rel - * entry with a column list we'll switch it to false. - */ - bool pub_no_list = true; + Bitmapset *cols = NULL; /* * If the publication is FOR ALL TABLES then it is treated the same as @@ -1011,6 +1012,8 @@ pgoutput_column_list_init(PGOutputData *data, List *publications, */ if (!pub->alltables) { + bool pub_no_list = true; + /* * Check for the presence of a column list in this publication. * @@ -1024,51 +1027,48 @@ pgoutput_column_list_init(PGOutputData *data, List *publications, if (HeapTupleIsValid(cftuple)) { - /* - * Lookup the column list attribute. - * - * Note: We update the pub_no_list value directly, because if - * the value is NULL, we have no list (and vice versa). - */ + /* Lookup the column list attribute. */ cfdatum = SysCacheGetAttr(PUBLICATIONRELMAP, cftuple, Anum_pg_publication_rel_prattrs, &pub_no_list); - /* - * Build the column list bitmap in the per-entry context. - * - * We need to merge column lists from all publications, so we - * update the same bitmapset. If the column list is null, we - * interpret it as replicating all columns. - */ + /* Build the column list bitmap in the per-entry context. */ if (!pub_no_list) /* when not null */ { pgoutput_ensure_entry_cxt(data, entry); - entry->columns = pub_collist_to_bitmapset(entry->columns, - cfdatum, - entry->entry_cxt); + cols = pub_collist_to_bitmapset(cols, cfdatum, + entry->entry_cxt); + + /* + * If column list includes all the columns of the table, + * set it to NULL. + */ + if (bms_num_members(cols) == RelationGetNumberOfAttributes(relation)) + { + bms_free(cols); + cols = NULL; + } } + + ReleaseSysCache(cftuple); } } - /* - * Found a publication with no column list, so we're done. But first - * discard column list we might have from preceding publications. - */ - if (pub_no_list) + if (first) { - if (cftuple) - ReleaseSysCache(cftuple); - - bms_free(entry->columns); - entry->columns = NULL; - - break; + entry->columns = cols; + first = false; } - - ReleaseSysCache(cftuple); + else if (!bms_equal(entry->columns, cols)) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot use different column lists for table \"%s.%s\" in different publications", + get_namespace_name(RelationGetNamespace(relation)), + RelationGetRelationName(relation))); } /* loop all subscribed publications */ + + RelationClose(relation); } /* |