Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/cache')
-rw-r--r--src/backend/utils/cache/relcache.c57
1 files changed, 45 insertions, 12 deletions
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index d0892cee24d..422509f18d7 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -5706,12 +5706,19 @@ RelationGetExclusionInfo(Relation indexRelation,
* Get the publication information for the given relation.
*
* Traverse all the publications which the relation is in to get the
- * publication actions and validate the row filter expressions for such
- * publications if any. We consider the row filter expression as invalid if it
- * references any column which is not part of REPLICA IDENTITY.
+ * publication actions and validate:
+ * 1. The row filter expressions for such publications if any. We consider the
+ * row filter expression as invalid if it references any column which is not
+ * part of REPLICA IDENTITY.
+ * 2. The column list for such publication if any. We consider the column list
+ * invalid if REPLICA IDENTITY contains any column that is not part of it.
+ * 3. The generated columns of the relation for such publications. We consider
+ * any reference of an unpublished generated column in REPLICA IDENTITY as
+ * invalid.
*
* To avoid fetching the publication information repeatedly, we cache the
- * publication actions and row filter validation information.
+ * publication actions, row filter validation information, column list
+ * validation information, and generated column validation information.
*/
void
RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc)
@@ -5734,6 +5741,8 @@ RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc)
pubdesc->rf_valid_for_delete = true;
pubdesc->cols_valid_for_update = true;
pubdesc->cols_valid_for_delete = true;
+ pubdesc->gencols_valid_for_update = true;
+ pubdesc->gencols_valid_for_delete = true;
return;
}
@@ -5748,6 +5757,8 @@ RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc)
pubdesc->rf_valid_for_delete = true;
pubdesc->cols_valid_for_update = true;
pubdesc->cols_valid_for_delete = true;
+ pubdesc->gencols_valid_for_update = true;
+ pubdesc->gencols_valid_for_delete = true;
/* Fetch the publication membership info. */
puboids = GetRelationPublications(relid);
@@ -5777,6 +5788,8 @@ RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc)
Oid pubid = lfirst_oid(lc);
HeapTuple tup;
Form_pg_publication pubform;
+ bool invalid_column_list;
+ bool invalid_gen_col;
tup = SearchSysCache1(PUBLICATIONOID, ObjectIdGetDatum(pubid));
@@ -5811,18 +5824,27 @@ RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc)
/*
* Check if all columns are part of the REPLICA IDENTITY index or not.
*
- * If the publication is FOR ALL TABLES then it means the table has no
- * column list and we can skip the validation.
+ * Check if all generated columns included in the REPLICA IDENTITY are
+ * published.
*/
- if (!pubform->puballtables &&
- (pubform->pubupdate || pubform->pubdelete) &&
- pub_collist_contains_invalid_column(pubid, relation, ancestors,
- pubform->pubviaroot))
+ if ((pubform->pubupdate || pubform->pubdelete) &&
+ pub_contains_invalid_column(pubid, relation, ancestors,
+ pubform->pubviaroot,
+ pubform->pubgencols,
+ &invalid_column_list,
+ &invalid_gen_col))
{
if (pubform->pubupdate)
- pubdesc->cols_valid_for_update = false;
+ {
+ pubdesc->cols_valid_for_update = !invalid_column_list;
+ pubdesc->gencols_valid_for_update = !invalid_gen_col;
+ }
+
if (pubform->pubdelete)
- pubdesc->cols_valid_for_delete = false;
+ {
+ pubdesc->cols_valid_for_delete = !invalid_column_list;
+ pubdesc->gencols_valid_for_delete = !invalid_gen_col;
+ }
}
ReleaseSysCache(tup);
@@ -5846,6 +5868,17 @@ RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc)
pubdesc->pubactions.pubdelete && pubdesc->pubactions.pubtruncate &&
!pubdesc->cols_valid_for_update && !pubdesc->cols_valid_for_delete)
break;
+
+ /*
+ * If we know everything is replicated and replica identity has an
+ * unpublished generated column, there is no point to check for other
+ * publications.
+ */
+ if (pubdesc->pubactions.pubinsert && pubdesc->pubactions.pubupdate &&
+ pubdesc->pubactions.pubdelete && pubdesc->pubactions.pubtruncate &&
+ !pubdesc->gencols_valid_for_update &&
+ !pubdesc->gencols_valid_for_delete)
+ break;
}
if (relation->rd_pubdesc)