1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-04 12:42:24 +03:00

Change publication's publish_generated_columns option type to enum.

The current boolean publish_generated_columns option only supports a
binary choice, which is insufficient for future enhancements where
generated columns can be of different types (e.g., stored or virtual). The
supported values for the publish_generated_columns option are 'none' and
'stored'.

Author: Vignesh C <vignesh21@gmail.com>
Reviewed-by: Peter Smith <smithpb2250@gmail.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Discussion: https://postgr.es/m/d718d219-dd47-4a33-bb97-56e8fc4da994@eisentraut.org
Discussion: https://postgr.es/m/B80D17B2-2C8E-4C7D-87F2-E5B4BE3C069E@gmail.com
This commit is contained in:
Amit Kapila 2025-01-23 15:28:37 +05:30
parent eef4a33f62
commit e65dbc9927
19 changed files with 394 additions and 230 deletions

View File

@ -6394,6 +6394,20 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
</para></entry> </para></entry>
</row> </row>
<row>
<entry role="catalog_table_entry"><para role="column_definition">
<structfield>pubgencols</structfield> <type>char</type>
</para>
<para>
Controls how to handle generated column replication when there is no
publication column list:
<literal>n</literal> = generated columns in the tables associated with
the publication should not be replicated,
<literal>s</literal> = stored generated columns in the tables associated
with the publication should be replicated.
</para></entry>
</row>
<row> <row>
<entry role="catalog_table_entry"><para role="column_definition"> <entry role="catalog_table_entry"><para role="column_definition">
<structfield>pubviaroot</structfield> <type>bool</type> <structfield>pubviaroot</structfield> <type>bool</type>

View File

@ -89,10 +89,10 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
<para> <para>
When a column list is specified, only the named columns are replicated. When a column list is specified, only the named columns are replicated.
The column list can contain generated columns as well. If no column list The column list can contain stored generated columns as well. If no
is specified, all table columns (except generated columns) are replicated column list is specified, all table columns (except generated columns)
through this publication, including any columns added later. It has no are replicated through this publication, including any columns added
effect on <literal>TRUNCATE</literal> commands. See later. It has no effect on <literal>TRUNCATE</literal> commands. See
<xref linkend="logical-replication-col-lists"/> for details about column <xref linkend="logical-replication-col-lists"/> for details about column
lists. lists.
</para> </para>
@ -190,20 +190,31 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
</varlistentry> </varlistentry>
<varlistentry id="sql-createpublication-params-with-publish-generated-columns"> <varlistentry id="sql-createpublication-params-with-publish-generated-columns">
<term><literal>publish_generated_columns</literal> (<type>boolean</type>)</term> <term><literal>publish_generated_columns</literal> (<type>enum</type>)</term>
<listitem> <listitem>
<para> <para>
Specifies whether the generated columns present in the tables Specifies whether the generated columns present in the tables
associated with the publication should be replicated. associated with the publication should be replicated. Possible values
The default is <literal>false</literal>. are <literal>none</literal> and <literal>stored</literal>.
</para>
<para>
The default is <literal>none</literal> meaning the generated
columns present in the tables associated with publication will not be
replicated.
</para>
<para>
If set to <literal>stored</literal>, the stored generated columns
present in the tables associated with publication will be replicated.
</para> </para>
<note> <note>
<para> <para>
If the subscriber is from a release prior to 18, then initial table If the subscriber is from a release prior to 18, then initial table
synchronization won't copy generated columns even if parameter synchronization won't copy generated columns even if parameter
<literal>publish_generated_columns</literal> is true in the <literal>publish_generated_columns</literal> is <literal>stored</literal>
publisher. in the publisher.
</para> </para>
</note> </note>
</listitem> </listitem>

View File

@ -622,10 +622,11 @@ pub_collist_to_bitmapset(Bitmapset *columns, Datum pubcols, MemoryContext mcxt)
/* /*
* Returns a bitmap representing the columns of the specified table. * Returns a bitmap representing the columns of the specified table.
* *
* Generated columns are included if include_gencols is true. * Generated columns are included if include_gencols_type is
* PUBLISH_GENCOLS_STORED.
*/ */
Bitmapset * Bitmapset *
pub_form_cols_map(Relation relation, bool include_gencols) pub_form_cols_map(Relation relation, PublishGencolsType include_gencols_type)
{ {
Bitmapset *result = NULL; Bitmapset *result = NULL;
TupleDesc desc = RelationGetDescr(relation); TupleDesc desc = RelationGetDescr(relation);
@ -634,9 +635,20 @@ pub_form_cols_map(Relation relation, bool include_gencols)
{ {
Form_pg_attribute att = TupleDescAttr(desc, i); Form_pg_attribute att = TupleDescAttr(desc, i);
if (att->attisdropped || (att->attgenerated && !include_gencols)) if (att->attisdropped)
continue; continue;
if (att->attgenerated)
{
/* We only support replication of STORED generated cols. */
if (att->attgenerated != ATTRIBUTE_GENERATED_STORED)
continue;
/* User hasn't requested to replicate STORED generated cols. */
if (include_gencols_type != PUBLISH_GENCOLS_STORED)
continue;
}
result = bms_add_member(result, att->attnum); result = bms_add_member(result, att->attnum);
} }
@ -1068,7 +1080,7 @@ GetPublication(Oid pubid)
pub->pubactions.pubdelete = pubform->pubdelete; pub->pubactions.pubdelete = pubform->pubdelete;
pub->pubactions.pubtruncate = pubform->pubtruncate; pub->pubactions.pubtruncate = pubform->pubtruncate;
pub->pubviaroot = pubform->pubviaroot; pub->pubviaroot = pubform->pubviaroot;
pub->pubgencols = pubform->pubgencols; pub->pubgencols_type = pubform->pubgencols_type;
ReleaseSysCache(tup); ReleaseSysCache(tup);
@ -1276,9 +1288,23 @@ pg_get_publication_tables(PG_FUNCTION_ARGS)
{ {
Form_pg_attribute att = TupleDescAttr(desc, i); Form_pg_attribute att = TupleDescAttr(desc, i);
if (att->attisdropped || (att->attgenerated && !pub->pubgencols)) if (att->attisdropped)
continue; continue;
if (att->attgenerated)
{
/* We only support replication of STORED generated cols. */
if (att->attgenerated != ATTRIBUTE_GENERATED_STORED)
continue;
/*
* User hasn't requested to replicate STORED generated
* cols.
*/
if (pub->pubgencols_type != PUBLISH_GENCOLS_STORED)
continue;
}
attnums[nattnums++] = att->attnum; attnums[nattnums++] = att->attnum;
} }

View File

@ -70,6 +70,7 @@ static void PublicationDropTables(Oid pubid, List *rels, bool missing_ok);
static void PublicationAddSchemas(Oid pubid, List *schemas, bool if_not_exists, static void PublicationAddSchemas(Oid pubid, List *schemas, bool if_not_exists,
AlterPublicationStmt *stmt); AlterPublicationStmt *stmt);
static void PublicationDropSchemas(Oid pubid, List *schemas, bool missing_ok); static void PublicationDropSchemas(Oid pubid, List *schemas, bool missing_ok);
static char defGetGeneratedColsOption(DefElem *def);
static void static void
@ -80,7 +81,7 @@ parse_publication_options(ParseState *pstate,
bool *publish_via_partition_root_given, bool *publish_via_partition_root_given,
bool *publish_via_partition_root, bool *publish_via_partition_root,
bool *publish_generated_columns_given, bool *publish_generated_columns_given,
bool *publish_generated_columns) char *publish_generated_columns)
{ {
ListCell *lc; ListCell *lc;
@ -94,7 +95,7 @@ parse_publication_options(ParseState *pstate,
pubactions->pubdelete = true; pubactions->pubdelete = true;
pubactions->pubtruncate = true; pubactions->pubtruncate = true;
*publish_via_partition_root = false; *publish_via_partition_root = false;
*publish_generated_columns = false; *publish_generated_columns = PUBLISH_GENCOLS_NONE;
/* Parse options */ /* Parse options */
foreach(lc, options) foreach(lc, options)
@ -160,7 +161,7 @@ parse_publication_options(ParseState *pstate,
if (*publish_generated_columns_given) if (*publish_generated_columns_given)
errorConflictingDefElem(defel, pstate); errorConflictingDefElem(defel, pstate);
*publish_generated_columns_given = true; *publish_generated_columns_given = true;
*publish_generated_columns = defGetBoolean(defel); *publish_generated_columns = defGetGeneratedColsOption(defel);
} }
else else
ereport(ERROR, ereport(ERROR,
@ -344,15 +345,16 @@ pub_rf_contains_invalid_column(Oid pubid, Relation relation, List *ancestors,
* by the column list. If any column is missing, *invalid_column_list is set * by the column list. If any column is missing, *invalid_column_list is set
* to true. * to true.
* 2. Ensures that all the generated columns referenced in the REPLICA IDENTITY * 2. Ensures that all the generated columns referenced in the REPLICA IDENTITY
* are published either by listing them in the column list or by enabling * are published, either by being explicitly named in the column list or, if
* publish_generated_columns option. If any unpublished generated column is * no column list is specified, by setting the option
* found, *invalid_gen_col is set to true. * publish_generated_columns to stored. If any unpublished
* generated column is found, *invalid_gen_col is set to true.
* *
* Returns true if any of the above conditions are not met. * Returns true if any of the above conditions are not met.
*/ */
bool bool
pub_contains_invalid_column(Oid pubid, Relation relation, List *ancestors, pub_contains_invalid_column(Oid pubid, Relation relation, List *ancestors,
bool pubviaroot, bool pubgencols, bool pubviaroot, char pubgencols_type,
bool *invalid_column_list, bool *invalid_column_list,
bool *invalid_gen_col) bool *invalid_gen_col)
{ {
@ -394,10 +396,10 @@ pub_contains_invalid_column(Oid pubid, Relation relation, List *ancestors,
/* /*
* As we don't allow a column list with REPLICA IDENTITY FULL, the * As we don't allow a column list with REPLICA IDENTITY FULL, the
* publish_generated_columns option must be set to true if the table * publish_generated_columns option must be set to stored if the table
* has any stored generated columns. * has any stored generated columns.
*/ */
if (!pubgencols && if (pubgencols_type != PUBLISH_GENCOLS_STORED &&
relation->rd_att->constr && relation->rd_att->constr &&
relation->rd_att->constr->has_generated_stored) relation->rd_att->constr->has_generated_stored)
*invalid_gen_col = true; *invalid_gen_col = true;
@ -425,10 +427,10 @@ pub_contains_invalid_column(Oid pubid, Relation relation, List *ancestors,
if (columns == NULL) if (columns == NULL)
{ {
/* /*
* The publish_generated_columns option must be set to true if the * The publish_generated_columns option must be set to stored if
* REPLICA IDENTITY contains any stored generated column. * the REPLICA IDENTITY contains any stored generated column.
*/ */
if (!pubgencols && att->attgenerated) if (pubgencols_type != PUBLISH_GENCOLS_STORED && att->attgenerated)
{ {
*invalid_gen_col = true; *invalid_gen_col = true;
break; break;
@ -775,7 +777,7 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
bool publish_via_partition_root_given; bool publish_via_partition_root_given;
bool publish_via_partition_root; bool publish_via_partition_root;
bool publish_generated_columns_given; bool publish_generated_columns_given;
bool publish_generated_columns; char publish_generated_columns;
AclResult aclresult; AclResult aclresult;
List *relations = NIL; List *relations = NIL;
List *schemaidlist = NIL; List *schemaidlist = NIL;
@ -834,8 +836,8 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
BoolGetDatum(pubactions.pubtruncate); BoolGetDatum(pubactions.pubtruncate);
values[Anum_pg_publication_pubviaroot - 1] = values[Anum_pg_publication_pubviaroot - 1] =
BoolGetDatum(publish_via_partition_root); BoolGetDatum(publish_via_partition_root);
values[Anum_pg_publication_pubgencols - 1] = values[Anum_pg_publication_pubgencols_type - 1] =
BoolGetDatum(publish_generated_columns); CharGetDatum(publish_generated_columns);
tup = heap_form_tuple(RelationGetDescr(rel), values, nulls); tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
@ -922,7 +924,7 @@ AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt,
bool publish_via_partition_root_given; bool publish_via_partition_root_given;
bool publish_via_partition_root; bool publish_via_partition_root;
bool publish_generated_columns_given; bool publish_generated_columns_given;
bool publish_generated_columns; char publish_generated_columns;
ObjectAddress obj; ObjectAddress obj;
Form_pg_publication pubform; Form_pg_publication pubform;
List *root_relids = NIL; List *root_relids = NIL;
@ -1046,8 +1048,8 @@ AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt,
if (publish_generated_columns_given) if (publish_generated_columns_given)
{ {
values[Anum_pg_publication_pubgencols - 1] = BoolGetDatum(publish_generated_columns); values[Anum_pg_publication_pubgencols_type - 1] = CharGetDatum(publish_generated_columns);
replaces[Anum_pg_publication_pubgencols - 1] = true; replaces[Anum_pg_publication_pubgencols_type - 1] = true;
} }
tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls, tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls,
@ -2043,3 +2045,33 @@ AlterPublicationOwner_oid(Oid subid, Oid newOwnerId)
table_close(rel, RowExclusiveLock); table_close(rel, RowExclusiveLock);
} }
/*
* Extract the publish_generated_columns option value from a DefElem. "stored"
* and "none" values are accepted.
*/
static char
defGetGeneratedColsOption(DefElem *def)
{
char *sval;
/*
* If no parameter value given, assume "stored" is meant.
*/
if (!def->arg)
return PUBLISH_GENCOLS_STORED;
sval = defGetString(def);
if (pg_strcasecmp(sval, "none") == 0)
return PUBLISH_GENCOLS_NONE;
if (pg_strcasecmp(sval, "stored") == 0)
return PUBLISH_GENCOLS_STORED;
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR),
errmsg("%s requires a \"none\" or \"stored\" value",
def->defname));
return PUBLISH_GENCOLS_NONE; /* keep compiler quiet */
}

View File

@ -30,11 +30,12 @@
#define TRUNCATE_RESTART_SEQS (1<<1) #define TRUNCATE_RESTART_SEQS (1<<1)
static void logicalrep_write_attrs(StringInfo out, Relation rel, static void logicalrep_write_attrs(StringInfo out, Relation rel,
Bitmapset *columns, bool include_gencols); Bitmapset *columns,
PublishGencolsType include_gencols_type);
static void logicalrep_write_tuple(StringInfo out, Relation rel, static void logicalrep_write_tuple(StringInfo out, Relation rel,
TupleTableSlot *slot, TupleTableSlot *slot,
bool binary, Bitmapset *columns, bool binary, Bitmapset *columns,
bool include_gencols); PublishGencolsType include_gencols_type);
static void logicalrep_read_attrs(StringInfo in, LogicalRepRelation *rel); static void logicalrep_read_attrs(StringInfo in, LogicalRepRelation *rel);
static void logicalrep_read_tuple(StringInfo in, LogicalRepTupleData *tuple); static void logicalrep_read_tuple(StringInfo in, LogicalRepTupleData *tuple);
@ -401,7 +402,8 @@ logicalrep_read_origin(StringInfo in, XLogRecPtr *origin_lsn)
void void
logicalrep_write_insert(StringInfo out, TransactionId xid, Relation rel, logicalrep_write_insert(StringInfo out, TransactionId xid, Relation rel,
TupleTableSlot *newslot, bool binary, TupleTableSlot *newslot, bool binary,
Bitmapset *columns, bool include_gencols) Bitmapset *columns,
PublishGencolsType include_gencols_type)
{ {
pq_sendbyte(out, LOGICAL_REP_MSG_INSERT); pq_sendbyte(out, LOGICAL_REP_MSG_INSERT);
@ -413,7 +415,8 @@ logicalrep_write_insert(StringInfo out, TransactionId xid, Relation rel,
pq_sendint32(out, RelationGetRelid(rel)); pq_sendint32(out, RelationGetRelid(rel));
pq_sendbyte(out, 'N'); /* new tuple follows */ pq_sendbyte(out, 'N'); /* new tuple follows */
logicalrep_write_tuple(out, rel, newslot, binary, columns, include_gencols); logicalrep_write_tuple(out, rel, newslot, binary, columns,
include_gencols_type);
} }
/* /*
@ -446,7 +449,8 @@ logicalrep_read_insert(StringInfo in, LogicalRepTupleData *newtup)
void void
logicalrep_write_update(StringInfo out, TransactionId xid, Relation rel, logicalrep_write_update(StringInfo out, TransactionId xid, Relation rel,
TupleTableSlot *oldslot, TupleTableSlot *newslot, TupleTableSlot *oldslot, TupleTableSlot *newslot,
bool binary, Bitmapset *columns, bool include_gencols) bool binary, Bitmapset *columns,
PublishGencolsType include_gencols_type)
{ {
pq_sendbyte(out, LOGICAL_REP_MSG_UPDATE); pq_sendbyte(out, LOGICAL_REP_MSG_UPDATE);
@ -468,11 +472,12 @@ logicalrep_write_update(StringInfo out, TransactionId xid, Relation rel,
else else
pq_sendbyte(out, 'K'); /* old key follows */ pq_sendbyte(out, 'K'); /* old key follows */
logicalrep_write_tuple(out, rel, oldslot, binary, columns, logicalrep_write_tuple(out, rel, oldslot, binary, columns,
include_gencols); include_gencols_type);
} }
pq_sendbyte(out, 'N'); /* new tuple follows */ pq_sendbyte(out, 'N'); /* new tuple follows */
logicalrep_write_tuple(out, rel, newslot, binary, columns, include_gencols); logicalrep_write_tuple(out, rel, newslot, binary, columns,
include_gencols_type);
} }
/* /*
@ -522,7 +527,8 @@ logicalrep_read_update(StringInfo in, bool *has_oldtuple,
void void
logicalrep_write_delete(StringInfo out, TransactionId xid, Relation rel, logicalrep_write_delete(StringInfo out, TransactionId xid, Relation rel,
TupleTableSlot *oldslot, bool binary, TupleTableSlot *oldslot, bool binary,
Bitmapset *columns, bool include_gencols) Bitmapset *columns,
PublishGencolsType include_gencols_type)
{ {
Assert(rel->rd_rel->relreplident == REPLICA_IDENTITY_DEFAULT || Assert(rel->rd_rel->relreplident == REPLICA_IDENTITY_DEFAULT ||
rel->rd_rel->relreplident == REPLICA_IDENTITY_FULL || rel->rd_rel->relreplident == REPLICA_IDENTITY_FULL ||
@ -542,7 +548,8 @@ logicalrep_write_delete(StringInfo out, TransactionId xid, Relation rel,
else else
pq_sendbyte(out, 'K'); /* old key follows */ pq_sendbyte(out, 'K'); /* old key follows */
logicalrep_write_tuple(out, rel, oldslot, binary, columns, include_gencols); logicalrep_write_tuple(out, rel, oldslot, binary, columns,
include_gencols_type);
} }
/* /*
@ -658,7 +665,8 @@ logicalrep_write_message(StringInfo out, TransactionId xid, XLogRecPtr lsn,
*/ */
void void
logicalrep_write_rel(StringInfo out, TransactionId xid, Relation rel, logicalrep_write_rel(StringInfo out, TransactionId xid, Relation rel,
Bitmapset *columns, bool include_gencols) Bitmapset *columns,
PublishGencolsType include_gencols_type)
{ {
char *relname; char *relname;
@ -680,7 +688,7 @@ logicalrep_write_rel(StringInfo out, TransactionId xid, Relation rel,
pq_sendbyte(out, rel->rd_rel->relreplident); pq_sendbyte(out, rel->rd_rel->relreplident);
/* send the attribute info */ /* send the attribute info */
logicalrep_write_attrs(out, rel, columns, include_gencols); logicalrep_write_attrs(out, rel, columns, include_gencols_type);
} }
/* /*
@ -757,7 +765,8 @@ logicalrep_read_typ(StringInfo in, LogicalRepTyp *ltyp)
*/ */
static void static void
logicalrep_write_tuple(StringInfo out, Relation rel, TupleTableSlot *slot, logicalrep_write_tuple(StringInfo out, Relation rel, TupleTableSlot *slot,
bool binary, Bitmapset *columns, bool include_gencols) bool binary, Bitmapset *columns,
PublishGencolsType include_gencols_type)
{ {
TupleDesc desc; TupleDesc desc;
Datum *values; Datum *values;
@ -771,7 +780,8 @@ logicalrep_write_tuple(StringInfo out, Relation rel, TupleTableSlot *slot,
{ {
Form_pg_attribute att = TupleDescAttr(desc, i); Form_pg_attribute att = TupleDescAttr(desc, i);
if (!logicalrep_should_publish_column(att, columns, include_gencols)) if (!logicalrep_should_publish_column(att, columns,
include_gencols_type))
continue; continue;
nliveatts++; nliveatts++;
@ -789,7 +799,8 @@ logicalrep_write_tuple(StringInfo out, Relation rel, TupleTableSlot *slot,
Form_pg_type typclass; Form_pg_type typclass;
Form_pg_attribute att = TupleDescAttr(desc, i); Form_pg_attribute att = TupleDescAttr(desc, i);
if (!logicalrep_should_publish_column(att, columns, include_gencols)) if (!logicalrep_should_publish_column(att, columns,
include_gencols_type))
continue; continue;
if (isnull[i]) if (isnull[i])
@ -908,7 +919,7 @@ logicalrep_read_tuple(StringInfo in, LogicalRepTupleData *tuple)
*/ */
static void static void
logicalrep_write_attrs(StringInfo out, Relation rel, Bitmapset *columns, logicalrep_write_attrs(StringInfo out, Relation rel, Bitmapset *columns,
bool include_gencols) PublishGencolsType include_gencols_type)
{ {
TupleDesc desc; TupleDesc desc;
int i; int i;
@ -923,7 +934,8 @@ logicalrep_write_attrs(StringInfo out, Relation rel, Bitmapset *columns,
{ {
Form_pg_attribute att = TupleDescAttr(desc, i); Form_pg_attribute att = TupleDescAttr(desc, i);
if (!logicalrep_should_publish_column(att, columns, include_gencols)) if (!logicalrep_should_publish_column(att, columns,
include_gencols_type))
continue; continue;
nliveatts++; nliveatts++;
@ -941,7 +953,8 @@ logicalrep_write_attrs(StringInfo out, Relation rel, Bitmapset *columns,
Form_pg_attribute att = TupleDescAttr(desc, i); Form_pg_attribute att = TupleDescAttr(desc, i);
uint8 flags = 0; uint8 flags = 0;
if (!logicalrep_should_publish_column(att, columns, include_gencols)) if (!logicalrep_should_publish_column(att, columns,
include_gencols_type))
continue; continue;
/* REPLICA IDENTITY FULL means all columns are sent as part of key. */ /* REPLICA IDENTITY FULL means all columns are sent as part of key. */
@ -1254,16 +1267,17 @@ logicalrep_message_type(LogicalRepMsgType action)
* *
* 'columns' represents the publication column list (if any) for that table. * 'columns' represents the publication column list (if any) for that table.
* *
* 'include_gencols' flag indicates whether generated columns should be * 'include_gencols_type' value indicates whether generated columns should be
* published when there is no column list. Typically, this will have the same * published when there is no column list. Typically, this will have the same
* value as the 'publish_generated_columns' publication parameter. * value as the 'publish_generated_columns' publication parameter.
* *
* Note that generated columns can be published only when present in a * Note that generated columns can be published only when present in a
* publication column list, or when include_gencols is true. * publication column list, or when include_gencols_type is
* PUBLISH_GENCOLS_STORED.
*/ */
bool bool
logicalrep_should_publish_column(Form_pg_attribute att, Bitmapset *columns, logicalrep_should_publish_column(Form_pg_attribute att, Bitmapset *columns,
bool include_gencols) PublishGencolsType include_gencols_type)
{ {
if (att->attisdropped) if (att->attisdropped)
return false; return false;
@ -1273,5 +1287,15 @@ logicalrep_should_publish_column(Form_pg_attribute att, Bitmapset *columns,
return bms_is_member(att->attnum, columns); return bms_is_member(att->attnum, columns);
/* All non-generated columns are always published. */ /* All non-generated columns are always published. */
return att->attgenerated ? include_gencols : true; if (!att->attgenerated)
return true;
/*
* Stored generated columns are only published when the user sets
* publish_generated_columns as stored.
*/
if (att->attgenerated == ATTRIBUTE_GENERATED_STORED)
return include_gencols_type == PUBLISH_GENCOLS_STORED;
return false;
} }

View File

@ -128,10 +128,13 @@ typedef struct RelationSyncEntry
bool schema_sent; bool schema_sent;
/* /*
* This is set if the 'publish_generated_columns' parameter is true, and * This will be PUBLISH_GENCOLS_STORED if the relation contains generated
* the relation contains generated columns. * columns and the 'publish_generated_columns' parameter is set to
* PUBLISH_GENCOLS_STORED. Otherwise, it will be PUBLISH_GENCOLS_NONE,
* indicating that no generated columns should be published, unless
* explicitly specified in the column list.
*/ */
bool include_gencols; PublishGencolsType include_gencols_type;
List *streamed_txns; /* streamed toplevel transactions with this List *streamed_txns; /* streamed toplevel transactions with this
* schema */ * schema */
@ -763,7 +766,7 @@ send_relation_and_attrs(Relation relation, TransactionId xid,
{ {
TupleDesc desc = RelationGetDescr(relation); TupleDesc desc = RelationGetDescr(relation);
Bitmapset *columns = relentry->columns; Bitmapset *columns = relentry->columns;
bool include_gencols = relentry->include_gencols; PublishGencolsType include_gencols_type = relentry->include_gencols_type;
int i; int i;
/* /*
@ -778,7 +781,8 @@ send_relation_and_attrs(Relation relation, TransactionId xid,
{ {
Form_pg_attribute att = TupleDescAttr(desc, i); Form_pg_attribute att = TupleDescAttr(desc, i);
if (!logicalrep_should_publish_column(att, columns, include_gencols)) if (!logicalrep_should_publish_column(att, columns,
include_gencols_type))
continue; continue;
if (att->atttypid < FirstGenbkiObjectId) if (att->atttypid < FirstGenbkiObjectId)
@ -790,7 +794,8 @@ send_relation_and_attrs(Relation relation, TransactionId xid,
} }
OutputPluginPrepareWrite(ctx, false); OutputPluginPrepareWrite(ctx, false);
logicalrep_write_rel(ctx->out, xid, relation, columns, include_gencols); logicalrep_write_rel(ctx->out, xid, relation, columns,
include_gencols_type);
OutputPluginWrite(ctx, false); OutputPluginWrite(ctx, false);
} }
@ -1044,7 +1049,7 @@ check_and_init_gencol(PGOutputData *data, List *publications,
/* There are no generated columns to be published. */ /* There are no generated columns to be published. */
if (!gencolpresent) if (!gencolpresent)
{ {
entry->include_gencols = false; entry->include_gencols_type = PUBLISH_GENCOLS_NONE;
return; return;
} }
@ -1064,10 +1069,10 @@ check_and_init_gencol(PGOutputData *data, List *publications,
if (first) if (first)
{ {
entry->include_gencols = pub->pubgencols; entry->include_gencols_type = pub->pubgencols_type;
first = false; first = false;
} }
else if (entry->include_gencols != pub->pubgencols) else if (entry->include_gencols_type != pub->pubgencols_type)
ereport(ERROR, ereport(ERROR,
errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot use different values of publish_generated_columns for table \"%s.%s\" in different publications", errmsg("cannot use different values of publish_generated_columns for table \"%s.%s\" in different publications",
@ -1131,7 +1136,8 @@ pgoutput_column_list_init(PGOutputData *data, List *publications,
{ {
MemoryContext oldcxt = MemoryContextSwitchTo(entry->entry_cxt); MemoryContext oldcxt = MemoryContextSwitchTo(entry->entry_cxt);
relcols = pub_form_cols_map(relation, entry->include_gencols); relcols = pub_form_cols_map(relation,
entry->include_gencols_type);
MemoryContextSwitchTo(oldcxt); MemoryContextSwitchTo(oldcxt);
} }
@ -1571,17 +1577,17 @@ pgoutput_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
case REORDER_BUFFER_CHANGE_INSERT: case REORDER_BUFFER_CHANGE_INSERT:
logicalrep_write_insert(ctx->out, xid, targetrel, new_slot, logicalrep_write_insert(ctx->out, xid, targetrel, new_slot,
data->binary, relentry->columns, data->binary, relentry->columns,
relentry->include_gencols); relentry->include_gencols_type);
break; break;
case REORDER_BUFFER_CHANGE_UPDATE: case REORDER_BUFFER_CHANGE_UPDATE:
logicalrep_write_update(ctx->out, xid, targetrel, old_slot, logicalrep_write_update(ctx->out, xid, targetrel, old_slot,
new_slot, data->binary, relentry->columns, new_slot, data->binary, relentry->columns,
relentry->include_gencols); relentry->include_gencols_type);
break; break;
case REORDER_BUFFER_CHANGE_DELETE: case REORDER_BUFFER_CHANGE_DELETE:
logicalrep_write_delete(ctx->out, xid, targetrel, old_slot, logicalrep_write_delete(ctx->out, xid, targetrel, old_slot,
data->binary, relentry->columns, data->binary, relentry->columns,
relentry->include_gencols); relentry->include_gencols_type);
break; break;
default: default:
Assert(false); Assert(false);
@ -2032,7 +2038,7 @@ get_rel_sync_entry(PGOutputData *data, Relation relation)
{ {
entry->replicate_valid = false; entry->replicate_valid = false;
entry->schema_sent = false; entry->schema_sent = false;
entry->include_gencols = false; entry->include_gencols_type = PUBLISH_GENCOLS_NONE;
entry->streamed_txns = NIL; entry->streamed_txns = NIL;
entry->pubactions.pubinsert = entry->pubactions.pubupdate = entry->pubactions.pubinsert = entry->pubactions.pubupdate =
entry->pubactions.pubdelete = entry->pubactions.pubtruncate = false; entry->pubactions.pubdelete = entry->pubactions.pubtruncate = false;
@ -2082,7 +2088,7 @@ get_rel_sync_entry(PGOutputData *data, Relation relation)
* earlier definition. * earlier definition.
*/ */
entry->schema_sent = false; entry->schema_sent = false;
entry->include_gencols = false; entry->include_gencols_type = PUBLISH_GENCOLS_NONE;
list_free(entry->streamed_txns); list_free(entry->streamed_txns);
entry->streamed_txns = NIL; entry->streamed_txns = NIL;
bms_free(entry->columns); bms_free(entry->columns);

View File

@ -5820,7 +5820,7 @@ RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc)
if ((pubform->pubupdate || pubform->pubdelete) && if ((pubform->pubupdate || pubform->pubdelete) &&
pub_contains_invalid_column(pubid, relation, ancestors, pub_contains_invalid_column(pubid, relation, ancestors,
pubform->pubviaroot, pubform->pubviaroot,
pubform->pubgencols, pubform->pubgencols_type,
&invalid_column_list, &invalid_column_list,
&invalid_gen_col)) &invalid_gen_col))
{ {

View File

@ -50,6 +50,7 @@
#include "catalog/pg_default_acl_d.h" #include "catalog/pg_default_acl_d.h"
#include "catalog/pg_largeobject_d.h" #include "catalog/pg_largeobject_d.h"
#include "catalog/pg_proc_d.h" #include "catalog/pg_proc_d.h"
#include "catalog/pg_publication_d.h"
#include "catalog/pg_subscription_d.h" #include "catalog/pg_subscription_d.h"
#include "catalog/pg_type_d.h" #include "catalog/pg_type_d.h"
#include "common/connect.h" #include "common/connect.h"
@ -4290,7 +4291,7 @@ getPublications(Archive *fout)
int i_pubdelete; int i_pubdelete;
int i_pubtruncate; int i_pubtruncate;
int i_pubviaroot; int i_pubviaroot;
int i_pubgencols; int i_pubgencols_type;
int i, int i,
ntups; ntups;
@ -4315,9 +4316,9 @@ getPublications(Archive *fout)
appendPQExpBufferStr(query, "false AS pubviaroot, "); appendPQExpBufferStr(query, "false AS pubviaroot, ");
if (fout->remoteVersion >= 180000) if (fout->remoteVersion >= 180000)
appendPQExpBufferStr(query, "p.pubgencols "); appendPQExpBufferStr(query, "p.pubgencols_type ");
else else
appendPQExpBufferStr(query, "false AS pubgencols "); appendPQExpBufferStr(query, CppAsString2(PUBLISH_GENCOLS_NONE) " AS pubgencols_type ");
appendPQExpBufferStr(query, "FROM pg_publication p"); appendPQExpBufferStr(query, "FROM pg_publication p");
@ -4338,7 +4339,7 @@ getPublications(Archive *fout)
i_pubdelete = PQfnumber(res, "pubdelete"); i_pubdelete = PQfnumber(res, "pubdelete");
i_pubtruncate = PQfnumber(res, "pubtruncate"); i_pubtruncate = PQfnumber(res, "pubtruncate");
i_pubviaroot = PQfnumber(res, "pubviaroot"); i_pubviaroot = PQfnumber(res, "pubviaroot");
i_pubgencols = PQfnumber(res, "pubgencols"); i_pubgencols_type = PQfnumber(res, "pubgencols_type");
pubinfo = pg_malloc(ntups * sizeof(PublicationInfo)); pubinfo = pg_malloc(ntups * sizeof(PublicationInfo));
@ -4363,8 +4364,8 @@ getPublications(Archive *fout)
(strcmp(PQgetvalue(res, i, i_pubtruncate), "t") == 0); (strcmp(PQgetvalue(res, i, i_pubtruncate), "t") == 0);
pubinfo[i].pubviaroot = pubinfo[i].pubviaroot =
(strcmp(PQgetvalue(res, i, i_pubviaroot), "t") == 0); (strcmp(PQgetvalue(res, i, i_pubviaroot), "t") == 0);
pubinfo[i].pubgencols = pubinfo[i].pubgencols_type =
(strcmp(PQgetvalue(res, i, i_pubgencols), "t") == 0); *(PQgetvalue(res, i, i_pubgencols_type));
/* Decide whether we want to dump it */ /* Decide whether we want to dump it */
selectDumpableObject(&(pubinfo[i].dobj), fout); selectDumpableObject(&(pubinfo[i].dobj), fout);
@ -4446,8 +4447,8 @@ dumpPublication(Archive *fout, const PublicationInfo *pubinfo)
if (pubinfo->pubviaroot) if (pubinfo->pubviaroot)
appendPQExpBufferStr(query, ", publish_via_partition_root = true"); appendPQExpBufferStr(query, ", publish_via_partition_root = true");
if (pubinfo->pubgencols) if (pubinfo->pubgencols_type == PUBLISH_GENCOLS_STORED)
appendPQExpBufferStr(query, ", publish_generated_columns = true"); appendPQExpBufferStr(query, ", publish_generated_columns = stored");
appendPQExpBufferStr(query, ");\n"); appendPQExpBufferStr(query, ");\n");

View File

@ -15,6 +15,7 @@
#define PG_DUMP_H #define PG_DUMP_H
#include "pg_backup.h" #include "pg_backup.h"
#include "catalog/pg_publication_d.h"
#define oidcmp(x,y) ( ((x) < (y) ? -1 : ((x) > (y)) ? 1 : 0) ) #define oidcmp(x,y) ( ((x) < (y) ? -1 : ((x) > (y)) ? 1 : 0) )
@ -638,7 +639,7 @@ typedef struct _PublicationInfo
bool pubdelete; bool pubdelete;
bool pubtruncate; bool pubtruncate;
bool pubviaroot; bool pubviaroot;
bool pubgencols; PublishGencolsType pubgencols_type;
} PublicationInfo; } PublicationInfo;
/* /*

View File

@ -3054,9 +3054,9 @@ my %tests = (
'CREATE PUBLICATION pub5' => { 'CREATE PUBLICATION pub5' => {
create_order => 50, create_order => 50,
create_sql => create_sql =>
'CREATE PUBLICATION pub5 WITH (publish_generated_columns = true);', 'CREATE PUBLICATION pub5 WITH (publish_generated_columns = stored);',
regexp => qr/^ regexp => qr/^
\QCREATE PUBLICATION pub5 WITH (publish = 'insert, update, delete, truncate', publish_generated_columns = true);\E \QCREATE PUBLICATION pub5 WITH (publish = 'insert, update, delete, truncate', publish_generated_columns = stored);\E
/xm, /xm,
like => { %full_runs, section_post_data => 1, }, like => { %full_runs, section_post_data => 1, },
}, },

View File

@ -24,6 +24,7 @@
#include "catalog/pg_constraint_d.h" #include "catalog/pg_constraint_d.h"
#include "catalog/pg_default_acl_d.h" #include "catalog/pg_default_acl_d.h"
#include "catalog/pg_proc_d.h" #include "catalog/pg_proc_d.h"
#include "catalog/pg_publication_d.h"
#include "catalog/pg_statistic_ext_d.h" #include "catalog/pg_statistic_ext_d.h"
#include "catalog/pg_subscription_d.h" #include "catalog/pg_subscription_d.h"
#include "catalog/pg_type_d.h" #include "catalog/pg_type_d.h"
@ -6372,7 +6373,12 @@ listPublications(const char *pattern)
gettext_noop("Truncates")); gettext_noop("Truncates"));
if (pset.sversion >= 180000) if (pset.sversion >= 180000)
appendPQExpBuffer(&buf, appendPQExpBuffer(&buf,
",\n pubgencols AS \"%s\"", ",\n (CASE pubgencols_type\n"
" WHEN '%c' THEN 'none'\n"
" WHEN '%c' THEN 'stored'\n"
" END) AS \"%s\"",
PUBLISH_GENCOLS_NONE,
PUBLISH_GENCOLS_STORED,
gettext_noop("Generated columns")); gettext_noop("Generated columns"));
if (pset.sversion >= 130000) if (pset.sversion >= 130000)
appendPQExpBuffer(&buf, appendPQExpBuffer(&buf,
@ -6500,11 +6506,17 @@ describePublications(const char *pattern)
", false AS pubtruncate"); ", false AS pubtruncate");
if (has_pubgencols) if (has_pubgencols)
appendPQExpBufferStr(&buf, appendPQExpBuffer(&buf,
", pubgencols"); ", (CASE pubgencols_type\n"
" WHEN '%c' THEN 'none'\n"
" WHEN '%c' THEN 'stored'\n"
" END) AS \"%s\"\n",
PUBLISH_GENCOLS_NONE,
PUBLISH_GENCOLS_STORED,
gettext_noop("Generated columns"));
else else
appendPQExpBufferStr(&buf, appendPQExpBufferStr(&buf,
", false AS pubgencols"); ", 'none' AS pubgencols");
if (has_pubviaroot) if (has_pubviaroot)
appendPQExpBufferStr(&buf, appendPQExpBufferStr(&buf,

View File

@ -57,6 +57,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 202501171 #define CATALOG_VERSION_NO 202501231
#endif #endif

View File

@ -55,8 +55,11 @@ CATALOG(pg_publication,6104,PublicationRelationId)
/* true if partition changes are published using root schema */ /* true if partition changes are published using root schema */
bool pubviaroot; bool pubviaroot;
/* true if generated columns data should be published */ /*
bool pubgencols; * 'n'(none) if generated column data should not be published. 's'(stored)
* if stored generated column data should be published.
*/
char pubgencols_type;
} FormData_pg_publication; } FormData_pg_publication;
/* ---------------- /* ----------------
@ -107,13 +110,27 @@ typedef struct PublicationDesc
bool gencols_valid_for_delete; bool gencols_valid_for_delete;
} PublicationDesc; } PublicationDesc;
#ifdef EXPOSE_TO_CLIENT_CODE
typedef enum PublishGencolsType
{
/* Generated columns present should not be replicated. */
PUBLISH_GENCOLS_NONE = 'n',
/* Generated columns present should be replicated. */
PUBLISH_GENCOLS_STORED = 's',
} PublishGencolsType;
#endif /* EXPOSE_TO_CLIENT_CODE */
typedef struct Publication typedef struct Publication
{ {
Oid oid; Oid oid;
char *name; char *name;
bool alltables; bool alltables;
bool pubviaroot; bool pubviaroot;
bool pubgencols; PublishGencolsType pubgencols_type;
PublicationActions pubactions; PublicationActions pubactions;
} Publication; } Publication;
@ -171,6 +188,7 @@ extern ObjectAddress publication_add_schema(Oid pubid, Oid schemaid,
extern Bitmapset *pub_collist_to_bitmapset(Bitmapset *columns, Datum pubcols, extern Bitmapset *pub_collist_to_bitmapset(Bitmapset *columns, Datum pubcols,
MemoryContext mcxt); MemoryContext mcxt);
extern Bitmapset *pub_form_cols_map(Relation relation, bool include_gencols); extern Bitmapset *pub_form_cols_map(Relation relation,
PublishGencolsType include_gencols_type);
#endif /* PG_PUBLICATION_H */ #endif /* PG_PUBLICATION_H */

View File

@ -35,7 +35,7 @@ extern bool pub_rf_contains_invalid_column(Oid pubid, Relation relation,
List *ancestors, bool pubviaroot); List *ancestors, bool pubviaroot);
extern bool pub_contains_invalid_column(Oid pubid, Relation relation, extern bool pub_contains_invalid_column(Oid pubid, Relation relation,
List *ancestors, bool pubviaroot, List *ancestors, bool pubviaroot,
bool pubgencols, char pubgencols_type,
bool *invalid_column_list, bool *invalid_column_list,
bool *invalid_gen_col); bool *invalid_gen_col);

View File

@ -225,19 +225,20 @@ extern char *logicalrep_read_origin(StringInfo in, XLogRecPtr *origin_lsn);
extern void logicalrep_write_insert(StringInfo out, TransactionId xid, extern void logicalrep_write_insert(StringInfo out, TransactionId xid,
Relation rel, TupleTableSlot *newslot, Relation rel, TupleTableSlot *newslot,
bool binary, Bitmapset *columns, bool binary, Bitmapset *columns,
bool include_gencols); PublishGencolsType include_gencols_type);
extern LogicalRepRelId logicalrep_read_insert(StringInfo in, LogicalRepTupleData *newtup); extern LogicalRepRelId logicalrep_read_insert(StringInfo in, LogicalRepTupleData *newtup);
extern void logicalrep_write_update(StringInfo out, TransactionId xid, extern void logicalrep_write_update(StringInfo out, TransactionId xid,
Relation rel, TupleTableSlot *oldslot, Relation rel, TupleTableSlot *oldslot,
TupleTableSlot *newslot, bool binary, TupleTableSlot *newslot, bool binary,
Bitmapset *columns, bool include_gencols); Bitmapset *columns,
PublishGencolsType include_gencols_type);
extern LogicalRepRelId logicalrep_read_update(StringInfo in, extern LogicalRepRelId logicalrep_read_update(StringInfo in,
bool *has_oldtuple, LogicalRepTupleData *oldtup, bool *has_oldtuple, LogicalRepTupleData *oldtup,
LogicalRepTupleData *newtup); LogicalRepTupleData *newtup);
extern void logicalrep_write_delete(StringInfo out, TransactionId xid, extern void logicalrep_write_delete(StringInfo out, TransactionId xid,
Relation rel, TupleTableSlot *oldslot, Relation rel, TupleTableSlot *oldslot,
bool binary, Bitmapset *columns, bool binary, Bitmapset *columns,
bool include_gencols); PublishGencolsType include_gencols_type);
extern LogicalRepRelId logicalrep_read_delete(StringInfo in, extern LogicalRepRelId logicalrep_read_delete(StringInfo in,
LogicalRepTupleData *oldtup); LogicalRepTupleData *oldtup);
extern void logicalrep_write_truncate(StringInfo out, TransactionId xid, extern void logicalrep_write_truncate(StringInfo out, TransactionId xid,
@ -249,7 +250,7 @@ extern void logicalrep_write_message(StringInfo out, TransactionId xid, XLogRecP
bool transactional, const char *prefix, Size sz, const char *message); bool transactional, const char *prefix, Size sz, const char *message);
extern void logicalrep_write_rel(StringInfo out, TransactionId xid, extern void logicalrep_write_rel(StringInfo out, TransactionId xid,
Relation rel, Bitmapset *columns, Relation rel, Bitmapset *columns,
bool include_gencols); PublishGencolsType include_gencols_type);
extern LogicalRepRelation *logicalrep_read_rel(StringInfo in); extern LogicalRepRelation *logicalrep_read_rel(StringInfo in);
extern void logicalrep_write_typ(StringInfo out, TransactionId xid, extern void logicalrep_write_typ(StringInfo out, TransactionId xid,
Oid typoid); Oid typoid);
@ -274,6 +275,6 @@ extern void logicalrep_read_stream_abort(StringInfo in,
extern const char *logicalrep_message_type(LogicalRepMsgType action); extern const char *logicalrep_message_type(LogicalRepMsgType action);
extern bool logicalrep_should_publish_column(Form_pg_attribute att, extern bool logicalrep_should_publish_column(Form_pg_attribute att,
Bitmapset *columns, Bitmapset *columns,
bool include_gencols); PublishGencolsType include_gencols_type);
#endif /* LOGICAL_PROTO_H */ #endif /* LOGICAL_PROTO_H */

View File

@ -17,7 +17,7 @@ SELECT obj_description(p.oid, 'pg_publication') FROM pg_publication p;
(1 row) (1 row)
SET client_min_messages = 'ERROR'; SET client_min_messages = 'ERROR';
CREATE PUBLICATION testpib_ins_trunct WITH (publish = insert); CREATE PUBLICATION testpub_ins_trunct WITH (publish = insert);
RESET client_min_messages; RESET client_min_messages;
ALTER PUBLICATION testpub_default SET (publish = update); ALTER PUBLICATION testpub_default SET (publish = update);
-- error cases -- error cases
@ -29,18 +29,18 @@ CREATE PUBLICATION testpub_xxx WITH (publish_via_partition_root = 'true', publis
ERROR: conflicting or redundant options ERROR: conflicting or redundant options
LINE 1: ...ub_xxx WITH (publish_via_partition_root = 'true', publish_vi... LINE 1: ...ub_xxx WITH (publish_via_partition_root = 'true', publish_vi...
^ ^
CREATE PUBLICATION testpub_xxx WITH (publish_generated_columns = 'true', publish_generated_columns = '0'); CREATE PUBLICATION testpub_xxx WITH (publish_generated_columns = stored, publish_generated_columns = none);
ERROR: conflicting or redundant options ERROR: conflicting or redundant options
LINE 1: ...pub_xxx WITH (publish_generated_columns = 'true', publish_ge... LINE 1: ...pub_xxx WITH (publish_generated_columns = stored, publish_ge...
^ ^
CREATE PUBLICATION testpub_xxx WITH (publish_generated_columns = 'foo'); CREATE PUBLICATION testpub_xxx WITH (publish_generated_columns = foo);
ERROR: publish_generated_columns requires a Boolean value ERROR: publish_generated_columns requires a "none" or "stored" value
\dRp \dRp
List of publications List of publications
Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------+--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------+--------------------------+------------+---------+---------+---------+-----------+-------------------+----------
testpib_ins_trunct | regress_publication_user | f | t | f | f | f | f | f testpub_default | regress_publication_user | f | f | t | f | f | none | f
testpub_default | regress_publication_user | f | f | t | f | f | f | f testpub_ins_trunct | regress_publication_user | f | t | f | f | f | none | f
(2 rows) (2 rows)
ALTER PUBLICATION testpub_default SET (publish = 'insert, update, delete'); ALTER PUBLICATION testpub_default SET (publish = 'insert, update, delete');
@ -48,8 +48,8 @@ ALTER PUBLICATION testpub_default SET (publish = 'insert, update, delete');
List of publications List of publications
Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------+--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------+--------------------------+------------+---------+---------+---------+-----------+-------------------+----------
testpib_ins_trunct | regress_publication_user | f | t | f | f | f | f | f testpub_default | regress_publication_user | f | t | t | t | f | none | f
testpub_default | regress_publication_user | f | t | t | t | f | f | f testpub_ins_trunct | regress_publication_user | f | t | f | f | f | none | f
(2 rows) (2 rows)
--- adding tables --- adding tables
@ -96,7 +96,7 @@ ALTER PUBLICATION testpub_fortable ADD TABLES IN SCHEMA pub_test;
Publication testpub_fortable Publication testpub_fortable
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables: Tables:
"public.testpub_tbl1" "public.testpub_tbl1"
Tables from schemas: Tables from schemas:
@ -108,7 +108,7 @@ ALTER PUBLICATION testpub_fortable DROP TABLES IN SCHEMA pub_test;
Publication testpub_fortable Publication testpub_fortable
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables: Tables:
"public.testpub_tbl1" "public.testpub_tbl1"
@ -118,7 +118,7 @@ ALTER PUBLICATION testpub_fortable SET TABLES IN SCHEMA pub_test;
Publication testpub_fortable Publication testpub_fortable
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables from schemas: Tables from schemas:
"pub_test" "pub_test"
@ -132,7 +132,7 @@ RESET client_min_messages;
Publication testpub_for_tbl_schema Publication testpub_for_tbl_schema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables: Tables:
"pub_test.testpub_nopk" "pub_test.testpub_nopk"
Tables from schemas: Tables from schemas:
@ -153,7 +153,7 @@ ALTER PUBLICATION testpub_forschema ADD TABLE pub_test.testpub_nopk;
Publication testpub_forschema Publication testpub_forschema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables: Tables:
"pub_test.testpub_nopk" "pub_test.testpub_nopk"
Tables from schemas: Tables from schemas:
@ -165,7 +165,7 @@ ALTER PUBLICATION testpub_forschema DROP TABLE pub_test.testpub_nopk;
Publication testpub_forschema Publication testpub_forschema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables from schemas: Tables from schemas:
"pub_test" "pub_test"
@ -179,7 +179,7 @@ ALTER PUBLICATION testpub_forschema SET TABLE pub_test.testpub_nopk;
Publication testpub_forschema Publication testpub_forschema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables: Tables:
"pub_test.testpub_nopk" "pub_test.testpub_nopk"
@ -206,7 +206,7 @@ Not-null constraints:
Publication testpub_foralltables Publication testpub_foralltables
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | t | t | t | f | f | f | f regress_publication_user | t | t | t | f | f | none | f
(1 row) (1 row)
DROP TABLE testpub_tbl2; DROP TABLE testpub_tbl2;
@ -221,7 +221,7 @@ RESET client_min_messages;
Publication testpub3 Publication testpub3
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables: Tables:
"public.testpub_tbl3" "public.testpub_tbl3"
"public.testpub_tbl3a" "public.testpub_tbl3a"
@ -230,7 +230,7 @@ Tables:
Publication testpub4 Publication testpub4
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables: Tables:
"public.testpub_tbl3" "public.testpub_tbl3"
@ -254,7 +254,7 @@ ALTER PUBLICATION testpub_forparted ADD TABLE testpub_parted;
Publication testpub_forparted Publication testpub_forparted
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables: Tables:
"public.testpub_parted" "public.testpub_parted"
@ -272,7 +272,7 @@ ALTER PUBLICATION testpub_forparted SET (publish_via_partition_root = true);
Publication testpub_forparted Publication testpub_forparted
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | t regress_publication_user | f | t | t | t | t | none | t
Tables: Tables:
"public.testpub_parted" "public.testpub_parted"
@ -304,7 +304,7 @@ RESET client_min_messages;
Publication testpub5 Publication testpub5
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | f | f | f | f | f regress_publication_user | f | t | f | f | f | none | f
Tables: Tables:
"public.testpub_rf_tbl1" "public.testpub_rf_tbl1"
"public.testpub_rf_tbl2" WHERE ((c <> 'test'::text) AND (d < 5)) "public.testpub_rf_tbl2" WHERE ((c <> 'test'::text) AND (d < 5))
@ -320,7 +320,7 @@ ALTER PUBLICATION testpub5 ADD TABLE testpub_rf_tbl3 WHERE (e > 1000 AND e < 200
Publication testpub5 Publication testpub5
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | f | f | f | f | f regress_publication_user | f | t | f | f | f | none | f
Tables: Tables:
"public.testpub_rf_tbl1" "public.testpub_rf_tbl1"
"public.testpub_rf_tbl2" WHERE ((c <> 'test'::text) AND (d < 5)) "public.testpub_rf_tbl2" WHERE ((c <> 'test'::text) AND (d < 5))
@ -339,7 +339,7 @@ ALTER PUBLICATION testpub5 DROP TABLE testpub_rf_tbl2;
Publication testpub5 Publication testpub5
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | f | f | f | f | f regress_publication_user | f | t | f | f | f | none | f
Tables: Tables:
"public.testpub_rf_tbl1" "public.testpub_rf_tbl1"
"public.testpub_rf_tbl3" WHERE ((e > 1000) AND (e < 2000)) "public.testpub_rf_tbl3" WHERE ((e > 1000) AND (e < 2000))
@ -350,7 +350,7 @@ ALTER PUBLICATION testpub5 SET TABLE testpub_rf_tbl3 WHERE (e > 300 AND e < 500)
Publication testpub5 Publication testpub5
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | f | f | f | f | f regress_publication_user | f | t | f | f | f | none | f
Tables: Tables:
"public.testpub_rf_tbl3" WHERE ((e > 300) AND (e < 500)) "public.testpub_rf_tbl3" WHERE ((e > 300) AND (e < 500))
@ -386,7 +386,7 @@ RESET client_min_messages;
Publication testpub_syntax1 Publication testpub_syntax1
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | f | f | f | f | f regress_publication_user | f | t | f | f | f | none | f
Tables: Tables:
"public.testpub_rf_tbl1" "public.testpub_rf_tbl1"
"public.testpub_rf_tbl3" WHERE (e < 999) "public.testpub_rf_tbl3" WHERE (e < 999)
@ -399,7 +399,7 @@ RESET client_min_messages;
Publication testpub_syntax2 Publication testpub_syntax2
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | f | f | f | f | f regress_publication_user | f | t | f | f | f | none | f
Tables: Tables:
"public.testpub_rf_tbl1" "public.testpub_rf_tbl1"
"testpub_rf_schema1.testpub_rf_tbl5" WHERE (h < 999) "testpub_rf_schema1.testpub_rf_tbl5" WHERE (h < 999)
@ -517,7 +517,7 @@ RESET client_min_messages;
Publication testpub6 Publication testpub6
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables: Tables:
"testpub_rf_schema2.testpub_rf_tbl6" WHERE (i < 99) "testpub_rf_schema2.testpub_rf_tbl6" WHERE (i < 99)
Tables from schemas: Tables from schemas:
@ -692,7 +692,7 @@ ERROR: cannot update table "testpub_gencol"
DETAIL: Replica identity must not contain unpublished generated columns. DETAIL: Replica identity must not contain unpublished generated columns.
DROP PUBLICATION pub_gencol; DROP PUBLICATION pub_gencol;
-- ok - generated column "b" is published explicitly -- ok - generated column "b" is published explicitly
CREATE PUBLICATION pub_gencol FOR TABLE testpub_gencol with (publish_generated_columns = true); CREATE PUBLICATION pub_gencol FOR TABLE testpub_gencol with (publish_generated_columns = stored);
UPDATE testpub_gencol SET a = 100 WHERE a = 1; UPDATE testpub_gencol SET a = 100 WHERE a = 1;
DROP PUBLICATION pub_gencol; DROP PUBLICATION pub_gencol;
DROP TABLE testpub_gencol; DROP TABLE testpub_gencol;
@ -767,7 +767,7 @@ ALTER PUBLICATION testpub_table_ins ADD TABLE testpub_tbl5 (a); -- ok
Publication testpub_table_ins Publication testpub_table_ins
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | f | f | t | f | f regress_publication_user | f | t | f | f | t | none | f
Tables: Tables:
"public.testpub_tbl5" (a) "public.testpub_tbl5" (a)
@ -960,7 +960,7 @@ ALTER PUBLICATION testpub_both_filters ADD TABLE testpub_tbl_both_filters (a,c)
Publication testpub_both_filters Publication testpub_both_filters
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables: Tables:
"public.testpub_tbl_both_filters" (a, c) WHERE (c <> 1) "public.testpub_tbl_both_filters" (a, c) WHERE (c <> 1)
@ -1171,7 +1171,7 @@ ERROR: publication "testpub_fortbl" already exists
Publication testpub_fortbl Publication testpub_fortbl
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables: Tables:
"pub_test.testpub_nopk" "pub_test.testpub_nopk"
"public.testpub_tbl1" "public.testpub_tbl1"
@ -1183,7 +1183,7 @@ DETAIL: This operation is not supported for views.
ALTER PUBLICATION testpub_default ADD TABLE testpub_tbl1; ALTER PUBLICATION testpub_default ADD TABLE testpub_tbl1;
ALTER PUBLICATION testpub_default SET TABLE testpub_tbl1; ALTER PUBLICATION testpub_default SET TABLE testpub_tbl1;
ALTER PUBLICATION testpub_default ADD TABLE pub_test.testpub_nopk; ALTER PUBLICATION testpub_default ADD TABLE pub_test.testpub_nopk;
ALTER PUBLICATION testpib_ins_trunct ADD TABLE pub_test.testpub_nopk, testpub_tbl1; ALTER PUBLICATION testpub_ins_trunct ADD TABLE pub_test.testpub_nopk, testpub_tbl1;
\d+ pub_test.testpub_nopk \d+ pub_test.testpub_nopk
Table "pub_test.testpub_nopk" Table "pub_test.testpub_nopk"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
@ -1191,9 +1191,9 @@ ALTER PUBLICATION testpib_ins_trunct ADD TABLE pub_test.testpub_nopk, testpub_tb
foo | integer | | | | plain | | foo | integer | | | | plain | |
bar | integer | | | | plain | | bar | integer | | | | plain | |
Publications: Publications:
"testpib_ins_trunct"
"testpub_default" "testpub_default"
"testpub_fortbl" "testpub_fortbl"
"testpub_ins_trunct"
\d+ testpub_tbl1 \d+ testpub_tbl1
Table "public.testpub_tbl1" Table "public.testpub_tbl1"
@ -1204,9 +1204,9 @@ Publications:
Indexes: Indexes:
"testpub_tbl1_pkey" PRIMARY KEY, btree (id) "testpub_tbl1_pkey" PRIMARY KEY, btree (id)
Publications: Publications:
"testpib_ins_trunct"
"testpub_default" "testpub_default"
"testpub_fortbl" "testpub_fortbl"
"testpub_ins_trunct"
Not-null constraints: Not-null constraints:
"testpub_tbl1_id_not_null" NOT NULL "id" "testpub_tbl1_id_not_null" NOT NULL "id"
@ -1214,7 +1214,7 @@ Not-null constraints:
Publication testpub_default Publication testpub_default
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | f | f | f regress_publication_user | f | t | t | t | f | none | f
Tables: Tables:
"pub_test.testpub_nopk" "pub_test.testpub_nopk"
"public.testpub_tbl1" "public.testpub_tbl1"
@ -1232,8 +1232,8 @@ ERROR: relation "testpub_nopk" is not part of the publication
Indexes: Indexes:
"testpub_tbl1_pkey" PRIMARY KEY, btree (id) "testpub_tbl1_pkey" PRIMARY KEY, btree (id)
Publications: Publications:
"testpib_ins_trunct"
"testpub_fortbl" "testpub_fortbl"
"testpub_ins_trunct"
Not-null constraints: Not-null constraints:
"testpub_tbl1_id_not_null" NOT NULL "id" "testpub_tbl1_id_not_null" NOT NULL "id"
@ -1297,7 +1297,7 @@ DROP TABLE testpub_tbl1;
Publication testpub_default Publication testpub_default
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | f | f | f regress_publication_user | f | t | t | t | f | none | f
(1 row) (1 row)
-- fail - must be owner of publication -- fail - must be owner of publication
@ -1310,7 +1310,7 @@ ALTER PUBLICATION testpub_default RENAME TO testpub_foo;
List of publications List of publications
Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
-------------+--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- -------------+--------------------------+------------+---------+---------+---------+-----------+-------------------+----------
testpub_foo | regress_publication_user | f | t | t | t | f | f | f testpub_foo | regress_publication_user | f | t | t | t | f | none | f
(1 row) (1 row)
-- rename back to keep the rest simple -- rename back to keep the rest simple
@ -1320,7 +1320,7 @@ ALTER PUBLICATION testpub_default OWNER TO regress_publication_user2;
List of publications List of publications
Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
-----------------+---------------------------+------------+---------+---------+---------+-----------+-------------------+---------- -----------------+---------------------------+------------+---------+---------+---------+-----------+-------------------+----------
testpub_default | regress_publication_user2 | f | t | t | t | f | f | f testpub_default | regress_publication_user2 | f | t | t | t | f | none | f
(1 row) (1 row)
-- adding schemas and tables -- adding schemas and tables
@ -1339,7 +1339,7 @@ CREATE PUBLICATION testpub1_forschema FOR TABLES IN SCHEMA pub_test1;
Publication testpub1_forschema Publication testpub1_forschema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables from schemas: Tables from schemas:
"pub_test1" "pub_test1"
@ -1348,7 +1348,7 @@ CREATE PUBLICATION testpub2_forschema FOR TABLES IN SCHEMA pub_test1, pub_test2,
Publication testpub2_forschema Publication testpub2_forschema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables from schemas: Tables from schemas:
"pub_test1" "pub_test1"
"pub_test2" "pub_test2"
@ -1365,7 +1365,7 @@ RESET client_min_messages;
Publication testpub3_forschema Publication testpub3_forschema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables from schemas: Tables from schemas:
"public" "public"
@ -1373,7 +1373,7 @@ Tables from schemas:
Publication testpub4_forschema Publication testpub4_forschema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables from schemas: Tables from schemas:
"CURRENT_SCHEMA" "CURRENT_SCHEMA"
@ -1381,7 +1381,7 @@ Tables from schemas:
Publication testpub5_forschema Publication testpub5_forschema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables from schemas: Tables from schemas:
"CURRENT_SCHEMA" "CURRENT_SCHEMA"
"public" "public"
@ -1390,7 +1390,7 @@ Tables from schemas:
Publication testpub6_forschema Publication testpub6_forschema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables from schemas: Tables from schemas:
"CURRENT_SCHEMA" "CURRENT_SCHEMA"
"public" "public"
@ -1399,7 +1399,7 @@ Tables from schemas:
Publication testpub_fortable Publication testpub_fortable
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables: Tables:
"CURRENT_SCHEMA.CURRENT_SCHEMA" "CURRENT_SCHEMA.CURRENT_SCHEMA"
@ -1436,7 +1436,7 @@ DROP SCHEMA pub_test3;
Publication testpub2_forschema Publication testpub2_forschema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables from schemas: Tables from schemas:
"pub_test1" "pub_test1"
"pub_test2" "pub_test2"
@ -1447,7 +1447,7 @@ ALTER SCHEMA pub_test1 RENAME to pub_test1_renamed;
Publication testpub2_forschema Publication testpub2_forschema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables from schemas: Tables from schemas:
"pub_test1_renamed" "pub_test1_renamed"
"pub_test2" "pub_test2"
@ -1457,7 +1457,7 @@ ALTER SCHEMA pub_test1_renamed RENAME to pub_test1;
Publication testpub2_forschema Publication testpub2_forschema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables from schemas: Tables from schemas:
"pub_test1" "pub_test1"
"pub_test2" "pub_test2"
@ -1468,7 +1468,7 @@ ALTER PUBLICATION testpub1_forschema ADD TABLES IN SCHEMA pub_test2;
Publication testpub1_forschema Publication testpub1_forschema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables from schemas: Tables from schemas:
"pub_test1" "pub_test1"
"pub_test2" "pub_test2"
@ -1480,7 +1480,7 @@ ERROR: schema "non_existent_schema" does not exist
Publication testpub1_forschema Publication testpub1_forschema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables from schemas: Tables from schemas:
"pub_test1" "pub_test1"
"pub_test2" "pub_test2"
@ -1492,7 +1492,7 @@ ERROR: schema "pub_test1" is already member of publication "testpub1_forschema"
Publication testpub1_forschema Publication testpub1_forschema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables from schemas: Tables from schemas:
"pub_test1" "pub_test1"
"pub_test2" "pub_test2"
@ -1503,7 +1503,7 @@ ALTER PUBLICATION testpub1_forschema DROP TABLES IN SCHEMA pub_test2;
Publication testpub1_forschema Publication testpub1_forschema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables from schemas: Tables from schemas:
"pub_test1" "pub_test1"
@ -1514,7 +1514,7 @@ ERROR: tables from schema "pub_test2" are not part of the publication
Publication testpub1_forschema Publication testpub1_forschema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables from schemas: Tables from schemas:
"pub_test1" "pub_test1"
@ -1525,7 +1525,7 @@ ERROR: schema "non_existent_schema" does not exist
Publication testpub1_forschema Publication testpub1_forschema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables from schemas: Tables from schemas:
"pub_test1" "pub_test1"
@ -1535,7 +1535,7 @@ ALTER PUBLICATION testpub1_forschema DROP TABLES IN SCHEMA pub_test1;
Publication testpub1_forschema Publication testpub1_forschema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
(1 row) (1 row)
-- alter publication set multiple schema -- alter publication set multiple schema
@ -1544,7 +1544,7 @@ ALTER PUBLICATION testpub1_forschema SET TABLES IN SCHEMA pub_test1, pub_test2;
Publication testpub1_forschema Publication testpub1_forschema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables from schemas: Tables from schemas:
"pub_test1" "pub_test1"
"pub_test2" "pub_test2"
@ -1556,7 +1556,7 @@ ERROR: schema "non_existent_schema" does not exist
Publication testpub1_forschema Publication testpub1_forschema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables from schemas: Tables from schemas:
"pub_test1" "pub_test1"
"pub_test2" "pub_test2"
@ -1568,7 +1568,7 @@ ALTER PUBLICATION testpub1_forschema SET TABLES IN SCHEMA pub_test1, pub_test1;
Publication testpub1_forschema Publication testpub1_forschema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables from schemas: Tables from schemas:
"pub_test1" "pub_test1"
@ -1650,7 +1650,7 @@ RESET client_min_messages;
Publication testpub3_forschema Publication testpub3_forschema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
(1 row) (1 row)
ALTER PUBLICATION testpub3_forschema SET TABLES IN SCHEMA pub_test1; ALTER PUBLICATION testpub3_forschema SET TABLES IN SCHEMA pub_test1;
@ -1658,7 +1658,7 @@ ALTER PUBLICATION testpub3_forschema SET TABLES IN SCHEMA pub_test1;
Publication testpub3_forschema Publication testpub3_forschema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables from schemas: Tables from schemas:
"pub_test1" "pub_test1"
@ -1671,7 +1671,7 @@ RESET client_min_messages;
Publication testpub_forschema_fortable Publication testpub_forschema_fortable
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables: Tables:
"pub_test2.tbl1" "pub_test2.tbl1"
Tables from schemas: Tables from schemas:
@ -1681,7 +1681,7 @@ Tables from schemas:
Publication testpub_fortable_forschema Publication testpub_fortable_forschema
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables: Tables:
"pub_test2.tbl1" "pub_test2.tbl1"
Tables from schemas: Tables from schemas:
@ -1696,7 +1696,7 @@ LINE 1: CREATE PUBLICATION testpub_error FOR pub_test2.tbl1;
DETAIL: One of TABLE or TABLES IN SCHEMA must be specified before a standalone table or schema name. DETAIL: One of TABLE or TABLES IN SCHEMA must be specified before a standalone table or schema name.
DROP VIEW testpub_view; DROP VIEW testpub_view;
DROP PUBLICATION testpub_default; DROP PUBLICATION testpub_default;
DROP PUBLICATION testpib_ins_trunct; DROP PUBLICATION testpub_ins_trunct;
DROP PUBLICATION testpub_fortbl; DROP PUBLICATION testpub_fortbl;
DROP PUBLICATION testpub1_forschema; DROP PUBLICATION testpub1_forschema;
DROP PUBLICATION testpub2_forschema; DROP PUBLICATION testpub2_forschema;
@ -1797,76 +1797,87 @@ DROP TABLE sch1.tbl1;
DROP SCHEMA sch1 cascade; DROP SCHEMA sch1 cascade;
DROP SCHEMA sch2 cascade; DROP SCHEMA sch2 cascade;
-- ====================================================== -- ======================================================
-- Test the publication 'publish_generated_columns' parameter enabled or disabled -- Test the 'publish_generated_columns' parameter with the following values:
-- 'stored', 'none', and the default (no value specified), which defaults to
-- 'stored'.
SET client_min_messages = 'ERROR'; SET client_min_messages = 'ERROR';
CREATE PUBLICATION pub1 FOR ALL TABLES WITH (publish_generated_columns=1); CREATE PUBLICATION pub1 FOR ALL TABLES WITH (publish_generated_columns = stored);
\dRp+ pub1 \dRp+ pub1
Publication pub1 Publication pub1
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | t | t | t | t | t | t | f regress_publication_user | t | t | t | t | t | stored | f
(1 row) (1 row)
CREATE PUBLICATION pub2 FOR ALL TABLES WITH (publish_generated_columns=0); CREATE PUBLICATION pub2 FOR ALL TABLES WITH (publish_generated_columns = none);
\dRp+ pub2 \dRp+ pub2
Publication pub2 Publication pub2
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | t | t | t | t | t | f | f regress_publication_user | t | t | t | t | t | none | f
(1 row)
CREATE PUBLICATION pub3 FOR ALL TABLES WITH (publish_generated_columns);
\dRp+ pub3
Publication pub3
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | t | t | t | t | t | stored | f
(1 row) (1 row)
DROP PUBLICATION pub1; DROP PUBLICATION pub1;
DROP PUBLICATION pub2; DROP PUBLICATION pub2;
-- Test the 'publish_generated_columns' parameter enabled or disabled for DROP PUBLICATION pub3;
-- Test the 'publish_generated_columns' parameter as 'none' and 'stored' for
-- different scenarios with/without generated columns in column lists. -- different scenarios with/without generated columns in column lists.
CREATE TABLE gencols (a int, gen1 int GENERATED ALWAYS AS (a * 2) STORED); CREATE TABLE gencols (a int, gen1 int GENERATED ALWAYS AS (a * 2) STORED);
-- Generated columns in column list, when 'publish_generated_columns'=false -- Generated columns in column list, when 'publish_generated_columns'='none'
CREATE PUBLICATION pub1 FOR table gencols(a, gen1) WITH (publish_generated_columns=false); CREATE PUBLICATION pub1 FOR table gencols(a, gen1) WITH (publish_generated_columns = none);
\dRp+ pub1 \dRp+ pub1
Publication pub1 Publication pub1
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables: Tables:
"public.gencols" (a, gen1) "public.gencols" (a, gen1)
-- Generated columns in column list, when 'publish_generated_columns'=true -- Generated columns in column list, when 'publish_generated_columns'='stored'
CREATE PUBLICATION pub2 FOR table gencols(a, gen1) WITH (publish_generated_columns=true); CREATE PUBLICATION pub2 FOR table gencols(a, gen1) WITH (publish_generated_columns = stored);
\dRp+ pub2 \dRp+ pub2
Publication pub2 Publication pub2
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | t | f regress_publication_user | f | t | t | t | t | stored | f
Tables: Tables:
"public.gencols" (a, gen1) "public.gencols" (a, gen1)
-- Generated columns in column list, then set 'publication_generate_columns'=false -- Generated columns in column list, then set 'publish_generated_columns'='none'
ALTER PUBLICATION pub2 SET (publish_generated_columns = false); ALTER PUBLICATION pub2 SET (publish_generated_columns = none);
\dRp+ pub2 \dRp+ pub2
Publication pub2 Publication pub2
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables: Tables:
"public.gencols" (a, gen1) "public.gencols" (a, gen1)
-- Remove generated columns from column list, when 'publish_generated_columns'=false -- Remove generated columns from column list, when 'publish_generated_columns'='none'
ALTER PUBLICATION pub2 SET TABLE gencols(a); ALTER PUBLICATION pub2 SET TABLE gencols(a);
\dRp+ pub2 \dRp+ pub2
Publication pub2 Publication pub2
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables: Tables:
"public.gencols" (a) "public.gencols" (a)
-- Add generated columns in column list, when 'publish_generated_columns'=false -- Add generated columns in column list, when 'publish_generated_columns'='none'
ALTER PUBLICATION pub2 SET TABLE gencols(a, gen1); ALTER PUBLICATION pub2 SET TABLE gencols(a, gen1);
\dRp+ pub2 \dRp+ pub2
Publication pub2 Publication pub2
Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root
--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- --------------------------+------------+---------+---------+---------+-----------+-------------------+----------
regress_publication_user | f | t | t | t | t | f | f regress_publication_user | f | t | t | t | t | none | f
Tables: Tables:
"public.gencols" (a, gen1) "public.gencols" (a, gen1)

View File

@ -15,7 +15,7 @@ COMMENT ON PUBLICATION testpub_default IS 'test publication';
SELECT obj_description(p.oid, 'pg_publication') FROM pg_publication p; SELECT obj_description(p.oid, 'pg_publication') FROM pg_publication p;
SET client_min_messages = 'ERROR'; SET client_min_messages = 'ERROR';
CREATE PUBLICATION testpib_ins_trunct WITH (publish = insert); CREATE PUBLICATION testpub_ins_trunct WITH (publish = insert);
RESET client_min_messages; RESET client_min_messages;
ALTER PUBLICATION testpub_default SET (publish = update); ALTER PUBLICATION testpub_default SET (publish = update);
@ -24,8 +24,8 @@ ALTER PUBLICATION testpub_default SET (publish = update);
CREATE PUBLICATION testpub_xxx WITH (foo); CREATE PUBLICATION testpub_xxx WITH (foo);
CREATE PUBLICATION testpub_xxx WITH (publish = 'cluster, vacuum'); CREATE PUBLICATION testpub_xxx WITH (publish = 'cluster, vacuum');
CREATE PUBLICATION testpub_xxx WITH (publish_via_partition_root = 'true', publish_via_partition_root = '0'); CREATE PUBLICATION testpub_xxx WITH (publish_via_partition_root = 'true', publish_via_partition_root = '0');
CREATE PUBLICATION testpub_xxx WITH (publish_generated_columns = 'true', publish_generated_columns = '0'); CREATE PUBLICATION testpub_xxx WITH (publish_generated_columns = stored, publish_generated_columns = none);
CREATE PUBLICATION testpub_xxx WITH (publish_generated_columns = 'foo'); CREATE PUBLICATION testpub_xxx WITH (publish_generated_columns = foo);
\dRp \dRp
@ -415,7 +415,7 @@ UPDATE testpub_gencol SET a = 100 WHERE a = 1;
DROP PUBLICATION pub_gencol; DROP PUBLICATION pub_gencol;
-- ok - generated column "b" is published explicitly -- ok - generated column "b" is published explicitly
CREATE PUBLICATION pub_gencol FOR TABLE testpub_gencol with (publish_generated_columns = true); CREATE PUBLICATION pub_gencol FOR TABLE testpub_gencol with (publish_generated_columns = stored);
UPDATE testpub_gencol SET a = 100 WHERE a = 1; UPDATE testpub_gencol SET a = 100 WHERE a = 1;
DROP PUBLICATION pub_gencol; DROP PUBLICATION pub_gencol;
@ -795,7 +795,7 @@ ALTER PUBLICATION testpub_default ADD TABLE testpub_tbl1;
ALTER PUBLICATION testpub_default SET TABLE testpub_tbl1; ALTER PUBLICATION testpub_default SET TABLE testpub_tbl1;
ALTER PUBLICATION testpub_default ADD TABLE pub_test.testpub_nopk; ALTER PUBLICATION testpub_default ADD TABLE pub_test.testpub_nopk;
ALTER PUBLICATION testpib_ins_trunct ADD TABLE pub_test.testpub_nopk, testpub_tbl1; ALTER PUBLICATION testpub_ins_trunct ADD TABLE pub_test.testpub_nopk, testpub_tbl1;
\d+ pub_test.testpub_nopk \d+ pub_test.testpub_nopk
\d+ testpub_tbl1 \d+ testpub_tbl1
@ -1074,7 +1074,7 @@ CREATE PUBLICATION testpub_error FOR pub_test2.tbl1;
DROP VIEW testpub_view; DROP VIEW testpub_view;
DROP PUBLICATION testpub_default; DROP PUBLICATION testpub_default;
DROP PUBLICATION testpib_ins_trunct; DROP PUBLICATION testpub_ins_trunct;
DROP PUBLICATION testpub_fortbl; DROP PUBLICATION testpub_fortbl;
DROP PUBLICATION testpub1_forschema; DROP PUBLICATION testpub1_forschema;
DROP PUBLICATION testpub2_forschema; DROP PUBLICATION testpub2_forschema;
@ -1142,37 +1142,42 @@ DROP SCHEMA sch1 cascade;
DROP SCHEMA sch2 cascade; DROP SCHEMA sch2 cascade;
-- ====================================================== -- ======================================================
-- Test the publication 'publish_generated_columns' parameter enabled or disabled -- Test the 'publish_generated_columns' parameter with the following values:
-- 'stored', 'none', and the default (no value specified), which defaults to
-- 'stored'.
SET client_min_messages = 'ERROR'; SET client_min_messages = 'ERROR';
CREATE PUBLICATION pub1 FOR ALL TABLES WITH (publish_generated_columns=1); CREATE PUBLICATION pub1 FOR ALL TABLES WITH (publish_generated_columns = stored);
\dRp+ pub1 \dRp+ pub1
CREATE PUBLICATION pub2 FOR ALL TABLES WITH (publish_generated_columns=0); CREATE PUBLICATION pub2 FOR ALL TABLES WITH (publish_generated_columns = none);
\dRp+ pub2 \dRp+ pub2
CREATE PUBLICATION pub3 FOR ALL TABLES WITH (publish_generated_columns);
\dRp+ pub3
DROP PUBLICATION pub1; DROP PUBLICATION pub1;
DROP PUBLICATION pub2; DROP PUBLICATION pub2;
DROP PUBLICATION pub3;
-- Test the 'publish_generated_columns' parameter enabled or disabled for -- Test the 'publish_generated_columns' parameter as 'none' and 'stored' for
-- different scenarios with/without generated columns in column lists. -- different scenarios with/without generated columns in column lists.
CREATE TABLE gencols (a int, gen1 int GENERATED ALWAYS AS (a * 2) STORED); CREATE TABLE gencols (a int, gen1 int GENERATED ALWAYS AS (a * 2) STORED);
-- Generated columns in column list, when 'publish_generated_columns'=false -- Generated columns in column list, when 'publish_generated_columns'='none'
CREATE PUBLICATION pub1 FOR table gencols(a, gen1) WITH (publish_generated_columns=false); CREATE PUBLICATION pub1 FOR table gencols(a, gen1) WITH (publish_generated_columns = none);
\dRp+ pub1 \dRp+ pub1
-- Generated columns in column list, when 'publish_generated_columns'=true -- Generated columns in column list, when 'publish_generated_columns'='stored'
CREATE PUBLICATION pub2 FOR table gencols(a, gen1) WITH (publish_generated_columns=true); CREATE PUBLICATION pub2 FOR table gencols(a, gen1) WITH (publish_generated_columns = stored);
\dRp+ pub2 \dRp+ pub2
-- Generated columns in column list, then set 'publication_generate_columns'=false -- Generated columns in column list, then set 'publish_generated_columns'='none'
ALTER PUBLICATION pub2 SET (publish_generated_columns = false); ALTER PUBLICATION pub2 SET (publish_generated_columns = none);
\dRp+ pub2 \dRp+ pub2
-- Remove generated columns from column list, when 'publish_generated_columns'=false -- Remove generated columns from column list, when 'publish_generated_columns'='none'
ALTER PUBLICATION pub2 SET TABLE gencols(a); ALTER PUBLICATION pub2 SET TABLE gencols(a);
\dRp+ pub2 \dRp+ pub2
-- Add generated columns in column list, when 'publish_generated_columns'=false -- Add generated columns in column list, when 'publish_generated_columns'='none'
ALTER PUBLICATION pub2 SET TABLE gencols(a, gen1); ALTER PUBLICATION pub2 SET TABLE gencols(a, gen1);
\dRp+ pub2 \dRp+ pub2

View File

@ -103,16 +103,16 @@ $node_publisher->safe_psql('postgres', "DROP PUBLICATION pub1");
# ============================================================================= # =============================================================================
# Exercise logical replication of a generated column to a subscriber side # Exercise logical replication of a generated column to a subscriber side
# regular column. This is done both when the publication parameter # regular column. This is done both when the publication parameter
# 'publish_generated_columns' is set to false (to confirm existing default # 'publish_generated_columns' is set to 'none' (to confirm existing default
# behavior), and is set to true (to confirm replication occurs). # behavior), and is set to 'stored' (to confirm replication occurs).
# #
# The test environment is set up as follows: # The test environment is set up as follows:
# #
# - Publication pub1 on the 'postgres' database. # - Publication pub1 on the 'postgres' database.
# pub1 has publish_generated_columns=false. # pub1 has publish_generated_columns as 'none'.
# #
# - Publication pub2 on the 'postgres' database. # - Publication pub2 on the 'postgres' database.
# pub2 has publish_generated_columns=true. # pub2 has publish_generated_columns as 'stored'.
# #
# - Subscription sub1 on the 'postgres' database for publication pub1. # - Subscription sub1 on the 'postgres' database for publication pub1.
# #
@ -132,8 +132,8 @@ $node_publisher->safe_psql(
'postgres', qq( 'postgres', qq(
CREATE TABLE tab_gen_to_nogen (a int, b int GENERATED ALWAYS AS (a * 2) STORED); CREATE TABLE tab_gen_to_nogen (a int, b int GENERATED ALWAYS AS (a * 2) STORED);
INSERT INTO tab_gen_to_nogen (a) VALUES (1), (2), (3); INSERT INTO tab_gen_to_nogen (a) VALUES (1), (2), (3);
CREATE PUBLICATION regress_pub1_gen_to_nogen FOR TABLE tab_gen_to_nogen WITH (publish_generated_columns = false); CREATE PUBLICATION regress_pub1_gen_to_nogen FOR TABLE tab_gen_to_nogen WITH (publish_generated_columns = none);
CREATE PUBLICATION regress_pub2_gen_to_nogen FOR TABLE tab_gen_to_nogen WITH (publish_generated_columns = true); CREATE PUBLICATION regress_pub2_gen_to_nogen FOR TABLE tab_gen_to_nogen WITH (publish_generated_columns = stored);
)); ));
# Create the table and subscription in the 'postgres' database. # Create the table and subscription in the 'postgres' database.
@ -157,28 +157,28 @@ $node_subscriber->wait_for_subscription_sync($node_publisher,
'regress_sub2_gen_to_nogen', 'test_pgc_true'); 'regress_sub2_gen_to_nogen', 'test_pgc_true');
# Verify that generated column data is not copied during the initial # Verify that generated column data is not copied during the initial
# synchronization when publish_generated_columns is set to false. # synchronization when publish_generated_columns is set to 'none'.
$result = $node_subscriber->safe_psql('postgres', $result = $node_subscriber->safe_psql('postgres',
"SELECT a, b FROM tab_gen_to_nogen ORDER BY a"); "SELECT a, b FROM tab_gen_to_nogen ORDER BY a");
is( $result, qq(1| is( $result, qq(1|
2| 2|
3|), 'tab_gen_to_nogen initial sync, when publish_generated_columns=false'); 3|), 'tab_gen_to_nogen initial sync, when publish_generated_columns=none');
# Verify that generated column data is copied during the initial synchronization # Verify that generated column data is copied during the initial synchronization
# when publish_generated_columns is set to true. # when publish_generated_columns is set to 'stored'.
$result = $node_subscriber->safe_psql('test_pgc_true', $result = $node_subscriber->safe_psql('test_pgc_true',
"SELECT a, b FROM tab_gen_to_nogen ORDER BY a"); "SELECT a, b FROM tab_gen_to_nogen ORDER BY a");
is( $result, qq(1|2 is( $result, qq(1|2
2|4 2|4
3|6), 3|6),
'tab_gen_to_nogen initial sync, when publish_generated_columns=true'); 'tab_gen_to_nogen initial sync, when publish_generated_columns=stored');
# Insert data to verify incremental replication. # Insert data to verify incremental replication.
$node_publisher->safe_psql('postgres', $node_publisher->safe_psql('postgres',
"INSERT INTO tab_gen_to_nogen VALUES (4), (5)"); "INSERT INTO tab_gen_to_nogen VALUES (4), (5)");
# Verify that the generated column data is not replicated during incremental # Verify that the generated column data is not replicated during incremental
# replication when publish_generated_columns is set to false. # replication when publish_generated_columns is set to 'none'.
$node_publisher->wait_for_catchup('regress_sub1_gen_to_nogen'); $node_publisher->wait_for_catchup('regress_sub1_gen_to_nogen');
$result = $node_subscriber->safe_psql('postgres', $result = $node_subscriber->safe_psql('postgres',
"SELECT a, b FROM tab_gen_to_nogen ORDER BY a"); "SELECT a, b FROM tab_gen_to_nogen ORDER BY a");
@ -187,11 +187,11 @@ is( $result, qq(1|
3| 3|
4| 4|
5|), 5|),
'tab_gen_to_nogen incremental replication, when publish_generated_columns=false' 'tab_gen_to_nogen incremental replication, when publish_generated_columns=none'
); );
# Verify that generated column data is replicated during incremental # Verify that generated column data is replicated during incremental
# synchronization when publish_generated_columns is set to true. # synchronization when publish_generated_columns is set to 'stored'.
$node_publisher->wait_for_catchup('regress_sub2_gen_to_nogen'); $node_publisher->wait_for_catchup('regress_sub2_gen_to_nogen');
$result = $node_subscriber->safe_psql('test_pgc_true', $result = $node_subscriber->safe_psql('test_pgc_true',
"SELECT a, b FROM tab_gen_to_nogen ORDER BY a"); "SELECT a, b FROM tab_gen_to_nogen ORDER BY a");
@ -200,7 +200,7 @@ is( $result, qq(1|2
3|6 3|6
4|8 4|8
5|10), 5|10),
'tab_gen_to_nogen incremental replication, when publish_generated_columns=true' 'tab_gen_to_nogen incremental replication, when publish_generated_columns=stored'
); );
# cleanup # cleanup
@ -221,15 +221,16 @@ $node_subscriber->safe_psql('postgres', "DROP DATABASE test_pgc_true");
# with the publication parameter 'publish_generated_columns'. # with the publication parameter 'publish_generated_columns'.
# #
# Test: Column lists take precedence, so generated columns in a column list # Test: Column lists take precedence, so generated columns in a column list
# will be replicated even when publish_generated_columns=false. # will be replicated even when publish_generated_columns is 'none'.
# #
# Test: When there is a column list, only those generated columns named in the # Test: When there is a column list, only those generated columns named in the
# column list will be replicated even when publish_generated_columns=true. # column list will be replicated even when publish_generated_columns is
# 'stored'.
# ============================================================================= # =============================================================================
# -------------------------------------------------- # --------------------------------------------------
# Test Case: Publisher replicates the column list, including generated columns, # Test Case: Publisher replicates the column list, including generated columns,
# even when the publish_generated_columns option is set to false. # even when the publish_generated_columns option is set to 'none'.
# -------------------------------------------------- # --------------------------------------------------
# Create table and publication. Insert data to verify initial sync. # Create table and publication. Insert data to verify initial sync.
@ -237,7 +238,7 @@ $node_publisher->safe_psql(
'postgres', qq( 'postgres', qq(
CREATE TABLE tab2 (a int, gen1 int GENERATED ALWAYS AS (a * 2) STORED); CREATE TABLE tab2 (a int, gen1 int GENERATED ALWAYS AS (a * 2) STORED);
INSERT INTO tab2 (a) VALUES (1), (2); INSERT INTO tab2 (a) VALUES (1), (2);
CREATE PUBLICATION pub1 FOR table tab2(gen1) WITH (publish_generated_columns=false); CREATE PUBLICATION pub1 FOR table tab2(gen1) WITH (publish_generated_columns=none);
)); ));
# Create table and subscription. # Create table and subscription.
@ -250,19 +251,19 @@ $node_subscriber->safe_psql(
# Wait for initial sync. # Wait for initial sync.
$node_subscriber->wait_for_subscription_sync($node_publisher, 'sub1'); $node_subscriber->wait_for_subscription_sync($node_publisher, 'sub1');
# Initial sync test when publish_generated_columns=false. # Initial sync test when publish_generated_columns is 'none'.
# Verify 'gen1' is replicated regardless of the false parameter value. # Verify 'gen1' is replicated regardless of the 'none' parameter value.
$result = $result =
$node_subscriber->safe_psql('postgres', "SELECT * FROM tab2 ORDER BY gen1"); $node_subscriber->safe_psql('postgres', "SELECT * FROM tab2 ORDER BY gen1");
is( $result, qq(|2 is( $result, qq(|2
|4), |4),
'tab2 initial sync, when publish_generated_columns=false'); 'tab2 initial sync, when publish_generated_columns=none');
# Insert data to verify incremental replication. # Insert data to verify incremental replication.
$node_publisher->safe_psql('postgres', "INSERT INTO tab2 VALUES (3), (4)"); $node_publisher->safe_psql('postgres', "INSERT INTO tab2 VALUES (3), (4)");
# Incremental replication test when publish_generated_columns=false. # Incremental replication test when publish_generated_columns is 'none'.
# Verify 'gen1' is replicated regardless of the false parameter value. # Verify 'gen1' is replicated regardless of the 'none' parameter value.
$node_publisher->wait_for_catchup('sub1'); $node_publisher->wait_for_catchup('sub1');
$result = $result =
$node_subscriber->safe_psql('postgres', "SELECT * FROM tab2 ORDER BY gen1"); $node_subscriber->safe_psql('postgres', "SELECT * FROM tab2 ORDER BY gen1");
@ -270,15 +271,15 @@ is( $result, qq(|2
|4 |4
|6 |6
|8), |8),
'tab2 incremental replication, when publish_generated_columns=false'); 'tab2 incremental replication, when publish_generated_columns=none');
# cleanup # cleanup
$node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION sub1"); $node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION sub1");
$node_publisher->safe_psql('postgres', "DROP PUBLICATION pub1"); $node_publisher->safe_psql('postgres', "DROP PUBLICATION pub1");
# -------------------------------------------------- # --------------------------------------------------
# Test Case: Even when publish_generated_columns is set to true, the publisher # Test Case: Even when publish_generated_columns is set to 'stored', the
# only publishes the data of columns specified in the column list, # publisher only publishes the data of columns specified in the column list,
# skipping other generated and non-generated columns. # skipping other generated and non-generated columns.
# -------------------------------------------------- # --------------------------------------------------
@ -287,7 +288,7 @@ $node_publisher->safe_psql(
'postgres', qq( 'postgres', qq(
CREATE TABLE tab3 (a int, gen1 int GENERATED ALWAYS AS (a * 2) STORED, gen2 int GENERATED ALWAYS AS (a * 2) STORED); CREATE TABLE tab3 (a int, gen1 int GENERATED ALWAYS AS (a * 2) STORED, gen2 int GENERATED ALWAYS AS (a * 2) STORED);
INSERT INTO tab3 (a) VALUES (1), (2); INSERT INTO tab3 (a) VALUES (1), (2);
CREATE PUBLICATION pub1 FOR table tab3(gen1) WITH (publish_generated_columns=true); CREATE PUBLICATION pub1 FOR table tab3(gen1) WITH (publish_generated_columns=stored);
)); ));
# Create table and subscription. # Create table and subscription.
@ -300,19 +301,19 @@ $node_subscriber->safe_psql(
# Wait for initial sync. # Wait for initial sync.
$node_subscriber->wait_for_subscription_sync($node_publisher, 'sub1'); $node_subscriber->wait_for_subscription_sync($node_publisher, 'sub1');
# Initial sync test when publish_generated_columns=true. # Initial sync test when publish_generated_columns is 'stored'.
# Verify only 'gen1' is replicated regardless of the true parameter value. # Verify only 'gen1' is replicated regardless of the 'stored' parameter value.
$result = $result =
$node_subscriber->safe_psql('postgres', "SELECT * FROM tab3 ORDER BY gen1"); $node_subscriber->safe_psql('postgres', "SELECT * FROM tab3 ORDER BY gen1");
is( $result, qq(|2| is( $result, qq(|2|
|4|), |4|),
'tab3 initial sync, when publish_generated_columns=true'); 'tab3 initial sync, when publish_generated_columns=stored');
# Insert data to verify incremental replication. # Insert data to verify incremental replication.
$node_publisher->safe_psql('postgres', "INSERT INTO tab3 VALUES (3), (4)"); $node_publisher->safe_psql('postgres', "INSERT INTO tab3 VALUES (3), (4)");
# Incremental replication test when publish_generated_columns=true. # Incremental replication test when publish_generated_columns is 'stored'.
# Verify only 'gen1' is replicated regardless of the true parameter value. # Verify only 'gen1' is replicated regardless of the 'stored' parameter value.
$node_publisher->wait_for_catchup('sub1'); $node_publisher->wait_for_catchup('sub1');
$result = $result =
$node_subscriber->safe_psql('postgres', "SELECT * FROM tab3 ORDER BY gen1"); $node_subscriber->safe_psql('postgres', "SELECT * FROM tab3 ORDER BY gen1");
@ -320,7 +321,7 @@ is( $result, qq(|2|
|4| |4|
|6| |6|
|8|), |8|),
'tab3 incremental replication, when publish_generated_columns=true'); 'tab3 incremental replication, when publish_generated_columns=stored');
# cleanup # cleanup
$node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION sub1"); $node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION sub1");

View File

@ -2276,6 +2276,7 @@ PublicationPartOpt
PublicationRelInfo PublicationRelInfo
PublicationSchemaInfo PublicationSchemaInfo
PublicationTable PublicationTable
PublishGencolsType
PullFilter PullFilter
PullFilterOps PullFilterOps
PushFilter PushFilter