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>
</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>
<entry role="catalog_table_entry"><para role="column_definition">
<structfield>pubviaroot</structfield> <type>bool</type>

View File

@ -89,10 +89,10 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
<para>
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
is specified, all table columns (except generated columns) are replicated
through this publication, including any columns added later. It has no
effect on <literal>TRUNCATE</literal> commands. See
The column list can contain stored generated columns as well. If no
column list is specified, all table columns (except generated columns)
are replicated through this publication, including any columns added
later. It has no effect on <literal>TRUNCATE</literal> commands. See
<xref linkend="logical-replication-col-lists"/> for details about column
lists.
</para>
@ -190,20 +190,31 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
</varlistentry>
<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>
<para>
Specifies whether the generated columns present in the tables
associated with the publication should be replicated.
The default is <literal>false</literal>.
associated with the publication should be replicated. Possible values
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>
<note>
<para>
If the subscriber is from a release prior to 18, then initial table
synchronization won't copy generated columns even if parameter
<literal>publish_generated_columns</literal> is true in the
publisher.
<literal>publish_generated_columns</literal> is <literal>stored</literal>
in the publisher.
</para>
</note>
</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.
*
* Generated columns are included if include_gencols is true.
* Generated columns are included if include_gencols_type is
* PUBLISH_GENCOLS_STORED.
*/
Bitmapset *
pub_form_cols_map(Relation relation, bool include_gencols)
pub_form_cols_map(Relation relation, PublishGencolsType include_gencols_type)
{
Bitmapset *result = NULL;
TupleDesc desc = RelationGetDescr(relation);
@ -634,9 +635,20 @@ pub_form_cols_map(Relation relation, bool include_gencols)
{
Form_pg_attribute att = TupleDescAttr(desc, i);
if (att->attisdropped || (att->attgenerated && !include_gencols))
if (att->attisdropped)
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);
}
@ -1068,7 +1080,7 @@ GetPublication(Oid pubid)
pub->pubactions.pubdelete = pubform->pubdelete;
pub->pubactions.pubtruncate = pubform->pubtruncate;
pub->pubviaroot = pubform->pubviaroot;
pub->pubgencols = pubform->pubgencols;
pub->pubgencols_type = pubform->pubgencols_type;
ReleaseSysCache(tup);
@ -1276,9 +1288,23 @@ pg_get_publication_tables(PG_FUNCTION_ARGS)
{
Form_pg_attribute att = TupleDescAttr(desc, i);
if (att->attisdropped || (att->attgenerated && !pub->pubgencols))
if (att->attisdropped)
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;
}

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,
AlterPublicationStmt *stmt);
static void PublicationDropSchemas(Oid pubid, List *schemas, bool missing_ok);
static char defGetGeneratedColsOption(DefElem *def);
static void
@ -80,7 +81,7 @@ parse_publication_options(ParseState *pstate,
bool *publish_via_partition_root_given,
bool *publish_via_partition_root,
bool *publish_generated_columns_given,
bool *publish_generated_columns)
char *publish_generated_columns)
{
ListCell *lc;
@ -94,7 +95,7 @@ parse_publication_options(ParseState *pstate,
pubactions->pubdelete = true;
pubactions->pubtruncate = true;
*publish_via_partition_root = false;
*publish_generated_columns = false;
*publish_generated_columns = PUBLISH_GENCOLS_NONE;
/* Parse options */
foreach(lc, options)
@ -160,7 +161,7 @@ parse_publication_options(ParseState *pstate,
if (*publish_generated_columns_given)
errorConflictingDefElem(defel, pstate);
*publish_generated_columns_given = true;
*publish_generated_columns = defGetBoolean(defel);
*publish_generated_columns = defGetGeneratedColsOption(defel);
}
else
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
* to true.
* 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
* publish_generated_columns option. If any unpublished generated column is
* found, *invalid_gen_col is set to true.
* are published, either by being explicitly named in the column list or, if
* no column list is specified, by setting the option
* 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.
*/
bool
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_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
* 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.
*/
if (!pubgencols &&
if (pubgencols_type != PUBLISH_GENCOLS_STORED &&
relation->rd_att->constr &&
relation->rd_att->constr->has_generated_stored)
*invalid_gen_col = true;
@ -425,10 +427,10 @@ pub_contains_invalid_column(Oid pubid, Relation relation, List *ancestors,
if (columns == NULL)
{
/*
* The publish_generated_columns option must be set to true if the
* REPLICA IDENTITY contains any stored generated column.
* The publish_generated_columns option must be set to stored if
* the REPLICA IDENTITY contains any stored generated column.
*/
if (!pubgencols && att->attgenerated)
if (pubgencols_type != PUBLISH_GENCOLS_STORED && att->attgenerated)
{
*invalid_gen_col = true;
break;
@ -775,7 +777,7 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
bool publish_via_partition_root_given;
bool publish_via_partition_root;
bool publish_generated_columns_given;
bool publish_generated_columns;
char publish_generated_columns;
AclResult aclresult;
List *relations = NIL;
List *schemaidlist = NIL;
@ -834,8 +836,8 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
BoolGetDatum(pubactions.pubtruncate);
values[Anum_pg_publication_pubviaroot - 1] =
BoolGetDatum(publish_via_partition_root);
values[Anum_pg_publication_pubgencols - 1] =
BoolGetDatum(publish_generated_columns);
values[Anum_pg_publication_pubgencols_type - 1] =
CharGetDatum(publish_generated_columns);
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;
bool publish_generated_columns_given;
bool publish_generated_columns;
char publish_generated_columns;
ObjectAddress obj;
Form_pg_publication pubform;
List *root_relids = NIL;
@ -1046,8 +1048,8 @@ AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt,
if (publish_generated_columns_given)
{
values[Anum_pg_publication_pubgencols - 1] = BoolGetDatum(publish_generated_columns);
replaces[Anum_pg_publication_pubgencols - 1] = true;
values[Anum_pg_publication_pubgencols_type - 1] = CharGetDatum(publish_generated_columns);
replaces[Anum_pg_publication_pubgencols_type - 1] = true;
}
tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls,
@ -2043,3 +2045,33 @@ AlterPublicationOwner_oid(Oid subid, Oid newOwnerId)
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)
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,
TupleTableSlot *slot,
bool binary, Bitmapset *columns,
bool include_gencols);
PublishGencolsType include_gencols_type);
static void logicalrep_read_attrs(StringInfo in, LogicalRepRelation *rel);
static void logicalrep_read_tuple(StringInfo in, LogicalRepTupleData *tuple);
@ -401,7 +402,8 @@ logicalrep_read_origin(StringInfo in, XLogRecPtr *origin_lsn)
void
logicalrep_write_insert(StringInfo out, TransactionId xid, Relation rel,
TupleTableSlot *newslot, bool binary,
Bitmapset *columns, bool include_gencols)
Bitmapset *columns,
PublishGencolsType include_gencols_type)
{
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_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
logicalrep_write_update(StringInfo out, TransactionId xid, Relation rel,
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);
@ -468,11 +472,12 @@ logicalrep_write_update(StringInfo out, TransactionId xid, Relation rel,
else
pq_sendbyte(out, 'K'); /* old key follows */
logicalrep_write_tuple(out, rel, oldslot, binary, columns,
include_gencols);
include_gencols_type);
}
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
logicalrep_write_delete(StringInfo out, TransactionId xid, Relation rel,
TupleTableSlot *oldslot, bool binary,
Bitmapset *columns, bool include_gencols)
Bitmapset *columns,
PublishGencolsType include_gencols_type)
{
Assert(rel->rd_rel->relreplident == REPLICA_IDENTITY_DEFAULT ||
rel->rd_rel->relreplident == REPLICA_IDENTITY_FULL ||
@ -542,7 +548,8 @@ logicalrep_write_delete(StringInfo out, TransactionId xid, Relation rel,
else
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
logicalrep_write_rel(StringInfo out, TransactionId xid, Relation rel,
Bitmapset *columns, bool include_gencols)
Bitmapset *columns,
PublishGencolsType include_gencols_type)
{
char *relname;
@ -680,7 +688,7 @@ logicalrep_write_rel(StringInfo out, TransactionId xid, Relation rel,
pq_sendbyte(out, rel->rd_rel->relreplident);
/* 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
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;
Datum *values;
@ -771,7 +780,8 @@ logicalrep_write_tuple(StringInfo out, Relation rel, TupleTableSlot *slot,
{
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;
nliveatts++;
@ -789,7 +799,8 @@ logicalrep_write_tuple(StringInfo out, Relation rel, TupleTableSlot *slot,
Form_pg_type typclass;
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;
if (isnull[i])
@ -908,7 +919,7 @@ logicalrep_read_tuple(StringInfo in, LogicalRepTupleData *tuple)
*/
static void
logicalrep_write_attrs(StringInfo out, Relation rel, Bitmapset *columns,
bool include_gencols)
PublishGencolsType include_gencols_type)
{
TupleDesc desc;
int i;
@ -923,7 +934,8 @@ logicalrep_write_attrs(StringInfo out, Relation rel, Bitmapset *columns,
{
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;
nliveatts++;
@ -941,7 +953,8 @@ logicalrep_write_attrs(StringInfo out, Relation rel, Bitmapset *columns,
Form_pg_attribute att = TupleDescAttr(desc, i);
uint8 flags = 0;
if (!logicalrep_should_publish_column(att, columns, include_gencols))
if (!logicalrep_should_publish_column(att, columns,
include_gencols_type))
continue;
/* 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.
*
* '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
* value as the 'publish_generated_columns' publication parameter.
*
* 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
logicalrep_should_publish_column(Form_pg_attribute att, Bitmapset *columns,
bool include_gencols)
PublishGencolsType include_gencols_type)
{
if (att->attisdropped)
return false;
@ -1273,5 +1287,15 @@ logicalrep_should_publish_column(Form_pg_attribute att, Bitmapset *columns,
return bms_is_member(att->attnum, columns);
/* 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;
/*
* This is set if the 'publish_generated_columns' parameter is true, and
* the relation contains generated columns.
* This will be PUBLISH_GENCOLS_STORED if the relation contains generated
* 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
* schema */
@ -763,7 +766,7 @@ send_relation_and_attrs(Relation relation, TransactionId xid,
{
TupleDesc desc = RelationGetDescr(relation);
Bitmapset *columns = relentry->columns;
bool include_gencols = relentry->include_gencols;
PublishGencolsType include_gencols_type = relentry->include_gencols_type;
int i;
/*
@ -778,7 +781,8 @@ send_relation_and_attrs(Relation relation, TransactionId xid,
{
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;
if (att->atttypid < FirstGenbkiObjectId)
@ -790,7 +794,8 @@ send_relation_and_attrs(Relation relation, TransactionId xid,
}
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);
}
@ -1044,7 +1049,7 @@ check_and_init_gencol(PGOutputData *data, List *publications,
/* There are no generated columns to be published. */
if (!gencolpresent)
{
entry->include_gencols = false;
entry->include_gencols_type = PUBLISH_GENCOLS_NONE;
return;
}
@ -1064,10 +1069,10 @@ check_and_init_gencol(PGOutputData *data, List *publications,
if (first)
{
entry->include_gencols = pub->pubgencols;
entry->include_gencols_type = pub->pubgencols_type;
first = false;
}
else if (entry->include_gencols != pub->pubgencols)
else if (entry->include_gencols_type != pub->pubgencols_type)
ereport(ERROR,
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
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);
relcols = pub_form_cols_map(relation, entry->include_gencols);
relcols = pub_form_cols_map(relation,
entry->include_gencols_type);
MemoryContextSwitchTo(oldcxt);
}
@ -1571,17 +1577,17 @@ pgoutput_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
case REORDER_BUFFER_CHANGE_INSERT:
logicalrep_write_insert(ctx->out, xid, targetrel, new_slot,
data->binary, relentry->columns,
relentry->include_gencols);
relentry->include_gencols_type);
break;
case REORDER_BUFFER_CHANGE_UPDATE:
logicalrep_write_update(ctx->out, xid, targetrel, old_slot,
new_slot, data->binary, relentry->columns,
relentry->include_gencols);
relentry->include_gencols_type);
break;
case REORDER_BUFFER_CHANGE_DELETE:
logicalrep_write_delete(ctx->out, xid, targetrel, old_slot,
data->binary, relentry->columns,
relentry->include_gencols);
relentry->include_gencols_type);
break;
default:
Assert(false);
@ -2032,7 +2038,7 @@ get_rel_sync_entry(PGOutputData *data, Relation relation)
{
entry->replicate_valid = false;
entry->schema_sent = false;
entry->include_gencols = false;
entry->include_gencols_type = PUBLISH_GENCOLS_NONE;
entry->streamed_txns = NIL;
entry->pubactions.pubinsert = entry->pubactions.pubupdate =
entry->pubactions.pubdelete = entry->pubactions.pubtruncate = false;
@ -2082,7 +2088,7 @@ get_rel_sync_entry(PGOutputData *data, Relation relation)
* earlier definition.
*/
entry->schema_sent = false;
entry->include_gencols = false;
entry->include_gencols_type = PUBLISH_GENCOLS_NONE;
list_free(entry->streamed_txns);
entry->streamed_txns = NIL;
bms_free(entry->columns);

View File

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

View File

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

View File

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

View File

@ -3054,9 +3054,9 @@ my %tests = (
'CREATE PUBLICATION pub5' => {
create_order => 50,
create_sql =>
'CREATE PUBLICATION pub5 WITH (publish_generated_columns = true);',
'CREATE PUBLICATION pub5 WITH (publish_generated_columns = stored);',
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,
like => { %full_runs, section_post_data => 1, },
},

View File

@ -24,6 +24,7 @@
#include "catalog/pg_constraint_d.h"
#include "catalog/pg_default_acl_d.h"
#include "catalog/pg_proc_d.h"
#include "catalog/pg_publication_d.h"
#include "catalog/pg_statistic_ext_d.h"
#include "catalog/pg_subscription_d.h"
#include "catalog/pg_type_d.h"
@ -6372,7 +6373,12 @@ listPublications(const char *pattern)
gettext_noop("Truncates"));
if (pset.sversion >= 180000)
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"));
if (pset.sversion >= 130000)
appendPQExpBuffer(&buf,
@ -6500,11 +6506,17 @@ describePublications(const char *pattern)
", false AS pubtruncate");
if (has_pubgencols)
appendPQExpBufferStr(&buf,
", pubgencols");
appendPQExpBuffer(&buf,
", (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
appendPQExpBufferStr(&buf,
", false AS pubgencols");
", 'none' AS pubgencols");
if (has_pubviaroot)
appendPQExpBufferStr(&buf,

View File

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

View File

@ -55,8 +55,11 @@ CATALOG(pg_publication,6104,PublicationRelationId)
/* true if partition changes are published using root schema */
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;
/* ----------------
@ -107,13 +110,27 @@ typedef struct PublicationDesc
bool gencols_valid_for_delete;
} 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
{
Oid oid;
char *name;
bool alltables;
bool pubviaroot;
bool pubgencols;
PublishGencolsType pubgencols_type;
PublicationActions pubactions;
} Publication;
@ -171,6 +188,7 @@ extern ObjectAddress publication_add_schema(Oid pubid, Oid schemaid,
extern Bitmapset *pub_collist_to_bitmapset(Bitmapset *columns, Datum pubcols,
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 */

View File

@ -35,7 +35,7 @@ extern bool pub_rf_contains_invalid_column(Oid pubid, Relation relation,
List *ancestors, bool pubviaroot);
extern bool pub_contains_invalid_column(Oid pubid, Relation relation,
List *ancestors, bool pubviaroot,
bool pubgencols,
char pubgencols_type,
bool *invalid_column_list,
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,
Relation rel, TupleTableSlot *newslot,
bool binary, Bitmapset *columns,
bool include_gencols);
PublishGencolsType include_gencols_type);
extern LogicalRepRelId logicalrep_read_insert(StringInfo in, LogicalRepTupleData *newtup);
extern void logicalrep_write_update(StringInfo out, TransactionId xid,
Relation rel, TupleTableSlot *oldslot,
TupleTableSlot *newslot, bool binary,
Bitmapset *columns, bool include_gencols);
Bitmapset *columns,
PublishGencolsType include_gencols_type);
extern LogicalRepRelId logicalrep_read_update(StringInfo in,
bool *has_oldtuple, LogicalRepTupleData *oldtup,
LogicalRepTupleData *newtup);
extern void logicalrep_write_delete(StringInfo out, TransactionId xid,
Relation rel, TupleTableSlot *oldslot,
bool binary, Bitmapset *columns,
bool include_gencols);
PublishGencolsType include_gencols_type);
extern LogicalRepRelId logicalrep_read_delete(StringInfo in,
LogicalRepTupleData *oldtup);
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);
extern void logicalrep_write_rel(StringInfo out, TransactionId xid,
Relation rel, Bitmapset *columns,
bool include_gencols);
PublishGencolsType include_gencols_type);
extern LogicalRepRelation *logicalrep_read_rel(StringInfo in);
extern void logicalrep_write_typ(StringInfo out, TransactionId xid,
Oid typoid);
@ -274,6 +275,6 @@ extern void logicalrep_read_stream_abort(StringInfo in,
extern const char *logicalrep_message_type(LogicalRepMsgType action);
extern bool logicalrep_should_publish_column(Form_pg_attribute att,
Bitmapset *columns,
bool include_gencols);
PublishGencolsType include_gencols_type);
#endif /* LOGICAL_PROTO_H */

View File

@ -17,7 +17,7 @@ SELECT obj_description(p.oid, 'pg_publication') FROM pg_publication p;
(1 row)
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;
ALTER PUBLICATION testpub_default SET (publish = update);
-- error cases
@ -29,18 +29,18 @@ CREATE PUBLICATION testpub_xxx WITH (publish_via_partition_root = 'true', publis
ERROR: conflicting or redundant options
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
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');
ERROR: publish_generated_columns requires a Boolean value
CREATE PUBLICATION testpub_xxx WITH (publish_generated_columns = foo);
ERROR: publish_generated_columns requires a "none" or "stored" value
\dRp
List of publications
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 | f | f
testpub_default | regress_publication_user | f | f | t | f | f | none | f
testpub_ins_trunct | regress_publication_user | f | t | f | f | f | none | f
(2 rows)
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
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 | f | f
testpub_default | regress_publication_user | f | t | t | t | f | none | f
testpub_ins_trunct | regress_publication_user | f | t | f | f | f | none | f
(2 rows)
--- adding tables
@ -96,7 +96,7 @@ ALTER PUBLICATION testpub_fortable ADD TABLES IN SCHEMA pub_test;
Publication testpub_fortable
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:
"public.testpub_tbl1"
Tables from schemas:
@ -108,7 +108,7 @@ ALTER PUBLICATION testpub_fortable DROP TABLES IN SCHEMA pub_test;
Publication testpub_fortable
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:
"public.testpub_tbl1"
@ -118,7 +118,7 @@ ALTER PUBLICATION testpub_fortable SET TABLES IN SCHEMA pub_test;
Publication testpub_fortable
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:
"pub_test"
@ -132,7 +132,7 @@ RESET client_min_messages;
Publication testpub_for_tbl_schema
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:
"pub_test.testpub_nopk"
Tables from schemas:
@ -153,7 +153,7 @@ ALTER PUBLICATION testpub_forschema ADD TABLE pub_test.testpub_nopk;
Publication testpub_forschema
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:
"pub_test.testpub_nopk"
Tables from schemas:
@ -165,7 +165,7 @@ ALTER PUBLICATION testpub_forschema DROP TABLE pub_test.testpub_nopk;
Publication testpub_forschema
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:
"pub_test"
@ -179,7 +179,7 @@ ALTER PUBLICATION testpub_forschema SET TABLE pub_test.testpub_nopk;
Publication testpub_forschema
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:
"pub_test.testpub_nopk"
@ -206,7 +206,7 @@ Not-null constraints:
Publication testpub_foralltables
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)
DROP TABLE testpub_tbl2;
@ -221,7 +221,7 @@ RESET client_min_messages;
Publication testpub3
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:
"public.testpub_tbl3"
"public.testpub_tbl3a"
@ -230,7 +230,7 @@ Tables:
Publication testpub4
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:
"public.testpub_tbl3"
@ -254,7 +254,7 @@ ALTER PUBLICATION testpub_forparted ADD TABLE testpub_parted;
Publication testpub_forparted
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:
"public.testpub_parted"
@ -272,7 +272,7 @@ ALTER PUBLICATION testpub_forparted SET (publish_via_partition_root = true);
Publication testpub_forparted
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:
"public.testpub_parted"
@ -304,7 +304,7 @@ RESET client_min_messages;
Publication testpub5
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:
"public.testpub_rf_tbl1"
"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
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:
"public.testpub_rf_tbl1"
"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
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:
"public.testpub_rf_tbl1"
"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
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:
"public.testpub_rf_tbl3" WHERE ((e > 300) AND (e < 500))
@ -386,7 +386,7 @@ RESET client_min_messages;
Publication testpub_syntax1
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:
"public.testpub_rf_tbl1"
"public.testpub_rf_tbl3" WHERE (e < 999)
@ -399,7 +399,7 @@ RESET client_min_messages;
Publication testpub_syntax2
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:
"public.testpub_rf_tbl1"
"testpub_rf_schema1.testpub_rf_tbl5" WHERE (h < 999)
@ -517,7 +517,7 @@ RESET client_min_messages;
Publication testpub6
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:
"testpub_rf_schema2.testpub_rf_tbl6" WHERE (i < 99)
Tables from schemas:
@ -692,7 +692,7 @@ ERROR: cannot update table "testpub_gencol"
DETAIL: Replica identity must not contain unpublished generated columns.
DROP PUBLICATION pub_gencol;
-- 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;
DROP PUBLICATION pub_gencol;
DROP TABLE testpub_gencol;
@ -767,7 +767,7 @@ ALTER PUBLICATION testpub_table_ins ADD TABLE testpub_tbl5 (a); -- ok
Publication testpub_table_ins
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:
"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
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:
"public.testpub_tbl_both_filters" (a, c) WHERE (c <> 1)
@ -1171,7 +1171,7 @@ ERROR: publication "testpub_fortbl" already exists
Publication testpub_fortbl
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:
"pub_test.testpub_nopk"
"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 SET TABLE testpub_tbl1;
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
Table "pub_test.testpub_nopk"
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 | |
bar | integer | | | | plain | |
Publications:
"testpib_ins_trunct"
"testpub_default"
"testpub_fortbl"
"testpub_ins_trunct"
\d+ testpub_tbl1
Table "public.testpub_tbl1"
@ -1204,9 +1204,9 @@ Publications:
Indexes:
"testpub_tbl1_pkey" PRIMARY KEY, btree (id)
Publications:
"testpib_ins_trunct"
"testpub_default"
"testpub_fortbl"
"testpub_ins_trunct"
Not-null constraints:
"testpub_tbl1_id_not_null" NOT NULL "id"
@ -1214,7 +1214,7 @@ Not-null constraints:
Publication testpub_default
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:
"pub_test.testpub_nopk"
"public.testpub_tbl1"
@ -1232,8 +1232,8 @@ ERROR: relation "testpub_nopk" is not part of the publication
Indexes:
"testpub_tbl1_pkey" PRIMARY KEY, btree (id)
Publications:
"testpib_ins_trunct"
"testpub_fortbl"
"testpub_ins_trunct"
Not-null constraints:
"testpub_tbl1_id_not_null" NOT NULL "id"
@ -1297,7 +1297,7 @@ DROP TABLE testpub_tbl1;
Publication testpub_default
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)
-- fail - must be owner of publication
@ -1310,7 +1310,7 @@ ALTER PUBLICATION testpub_default RENAME TO testpub_foo;
List of publications
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)
-- rename back to keep the rest simple
@ -1320,7 +1320,7 @@ ALTER PUBLICATION testpub_default OWNER TO regress_publication_user2;
List of publications
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)
-- adding schemas and tables
@ -1339,7 +1339,7 @@ CREATE PUBLICATION testpub1_forschema FOR TABLES IN SCHEMA pub_test1;
Publication testpub1_forschema
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:
"pub_test1"
@ -1348,7 +1348,7 @@ CREATE PUBLICATION testpub2_forschema FOR TABLES IN SCHEMA pub_test1, pub_test2,
Publication testpub2_forschema
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:
"pub_test1"
"pub_test2"
@ -1365,7 +1365,7 @@ RESET client_min_messages;
Publication testpub3_forschema
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:
"public"
@ -1373,7 +1373,7 @@ Tables from schemas:
Publication testpub4_forschema
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:
"CURRENT_SCHEMA"
@ -1381,7 +1381,7 @@ Tables from schemas:
Publication testpub5_forschema
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:
"CURRENT_SCHEMA"
"public"
@ -1390,7 +1390,7 @@ Tables from schemas:
Publication testpub6_forschema
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:
"CURRENT_SCHEMA"
"public"
@ -1399,7 +1399,7 @@ Tables from schemas:
Publication testpub_fortable
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:
"CURRENT_SCHEMA.CURRENT_SCHEMA"
@ -1436,7 +1436,7 @@ DROP SCHEMA pub_test3;
Publication testpub2_forschema
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:
"pub_test1"
"pub_test2"
@ -1447,7 +1447,7 @@ ALTER SCHEMA pub_test1 RENAME to pub_test1_renamed;
Publication testpub2_forschema
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:
"pub_test1_renamed"
"pub_test2"
@ -1457,7 +1457,7 @@ ALTER SCHEMA pub_test1_renamed RENAME to pub_test1;
Publication testpub2_forschema
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:
"pub_test1"
"pub_test2"
@ -1468,7 +1468,7 @@ ALTER PUBLICATION testpub1_forschema ADD TABLES IN SCHEMA pub_test2;
Publication testpub1_forschema
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:
"pub_test1"
"pub_test2"
@ -1480,7 +1480,7 @@ ERROR: schema "non_existent_schema" does not exist
Publication testpub1_forschema
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:
"pub_test1"
"pub_test2"
@ -1492,7 +1492,7 @@ ERROR: schema "pub_test1" is already member of publication "testpub1_forschema"
Publication testpub1_forschema
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:
"pub_test1"
"pub_test2"
@ -1503,7 +1503,7 @@ ALTER PUBLICATION testpub1_forschema DROP TABLES IN SCHEMA pub_test2;
Publication testpub1_forschema
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:
"pub_test1"
@ -1514,7 +1514,7 @@ ERROR: tables from schema "pub_test2" are not part of the publication
Publication testpub1_forschema
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:
"pub_test1"
@ -1525,7 +1525,7 @@ ERROR: schema "non_existent_schema" does not exist
Publication testpub1_forschema
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:
"pub_test1"
@ -1535,7 +1535,7 @@ ALTER PUBLICATION testpub1_forschema DROP TABLES IN SCHEMA pub_test1;
Publication testpub1_forschema
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)
-- alter publication set multiple schema
@ -1544,7 +1544,7 @@ ALTER PUBLICATION testpub1_forschema SET TABLES IN SCHEMA pub_test1, pub_test2;
Publication testpub1_forschema
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:
"pub_test1"
"pub_test2"
@ -1556,7 +1556,7 @@ ERROR: schema "non_existent_schema" does not exist
Publication testpub1_forschema
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:
"pub_test1"
"pub_test2"
@ -1568,7 +1568,7 @@ ALTER PUBLICATION testpub1_forschema SET TABLES IN SCHEMA pub_test1, pub_test1;
Publication testpub1_forschema
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:
"pub_test1"
@ -1650,7 +1650,7 @@ RESET client_min_messages;
Publication testpub3_forschema
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)
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
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:
"pub_test1"
@ -1671,7 +1671,7 @@ RESET client_min_messages;
Publication testpub_forschema_fortable
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:
"pub_test2.tbl1"
Tables from schemas:
@ -1681,7 +1681,7 @@ Tables from schemas:
Publication testpub_fortable_forschema
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:
"pub_test2.tbl1"
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.
DROP VIEW testpub_view;
DROP PUBLICATION testpub_default;
DROP PUBLICATION testpib_ins_trunct;
DROP PUBLICATION testpub_ins_trunct;
DROP PUBLICATION testpub_fortbl;
DROP PUBLICATION testpub1_forschema;
DROP PUBLICATION testpub2_forschema;
@ -1797,76 +1797,87 @@ DROP TABLE sch1.tbl1;
DROP SCHEMA sch1 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';
CREATE PUBLICATION pub1 FOR ALL TABLES WITH (publish_generated_columns=1);
CREATE PUBLICATION pub1 FOR ALL TABLES WITH (publish_generated_columns = stored);
\dRp+ pub1
Publication pub1
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)
CREATE PUBLICATION pub2 FOR ALL TABLES WITH (publish_generated_columns=0);
CREATE PUBLICATION pub2 FOR ALL TABLES WITH (publish_generated_columns = none);
\dRp+ pub2
Publication pub2
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)
DROP PUBLICATION pub1;
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.
CREATE TABLE gencols (a int, gen1 int GENERATED ALWAYS AS (a * 2) STORED);
-- Generated columns in column list, when 'publish_generated_columns'=false
CREATE PUBLICATION pub1 FOR table gencols(a, gen1) WITH (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 = none);
\dRp+ pub1
Publication pub1
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:
"public.gencols" (a, gen1)
-- Generated columns in column list, when 'publish_generated_columns'=true
CREATE PUBLICATION pub2 FOR table gencols(a, gen1) WITH (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 = stored);
\dRp+ pub2
Publication pub2
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:
"public.gencols" (a, gen1)
-- Generated columns in column list, then set 'publication_generate_columns'=false
ALTER PUBLICATION pub2 SET (publish_generated_columns = false);
-- Generated columns in column list, then set 'publish_generated_columns'='none'
ALTER PUBLICATION pub2 SET (publish_generated_columns = none);
\dRp+ pub2
Publication pub2
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:
"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);
\dRp+ pub2
Publication pub2
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:
"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);
\dRp+ pub2
Publication pub2
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:
"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;
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;
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 (publish = 'cluster, vacuum');
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 = 'foo');
CREATE PUBLICATION testpub_xxx WITH (publish_generated_columns = stored, publish_generated_columns = none);
CREATE PUBLICATION testpub_xxx WITH (publish_generated_columns = foo);
\dRp
@ -415,7 +415,7 @@ UPDATE testpub_gencol SET a = 100 WHERE a = 1;
DROP PUBLICATION pub_gencol;
-- 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;
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 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+ testpub_tbl1
@ -1074,7 +1074,7 @@ CREATE PUBLICATION testpub_error FOR pub_test2.tbl1;
DROP VIEW testpub_view;
DROP PUBLICATION testpub_default;
DROP PUBLICATION testpib_ins_trunct;
DROP PUBLICATION testpub_ins_trunct;
DROP PUBLICATION testpub_fortbl;
DROP PUBLICATION testpub1_forschema;
DROP PUBLICATION testpub2_forschema;
@ -1142,37 +1142,42 @@ DROP SCHEMA sch1 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';
CREATE PUBLICATION pub1 FOR ALL TABLES WITH (publish_generated_columns=1);
CREATE PUBLICATION pub1 FOR ALL TABLES WITH (publish_generated_columns = stored);
\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
CREATE PUBLICATION pub3 FOR ALL TABLES WITH (publish_generated_columns);
\dRp+ pub3
DROP PUBLICATION pub1;
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.
CREATE TABLE gencols (a int, gen1 int GENERATED ALWAYS AS (a * 2) STORED);
-- Generated columns in column list, when 'publish_generated_columns'=false
CREATE PUBLICATION pub1 FOR table gencols(a, gen1) WITH (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 = none);
\dRp+ pub1
-- Generated columns in column list, when 'publish_generated_columns'=true
CREATE PUBLICATION pub2 FOR table gencols(a, gen1) WITH (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 = stored);
\dRp+ pub2
-- Generated columns in column list, then set 'publication_generate_columns'=false
ALTER PUBLICATION pub2 SET (publish_generated_columns = false);
-- Generated columns in column list, then set 'publish_generated_columns'='none'
ALTER PUBLICATION pub2 SET (publish_generated_columns = none);
\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);
\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);
\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
# regular column. This is done both when the publication parameter
# 'publish_generated_columns' is set to false (to confirm existing default
# behavior), and is set to true (to confirm replication occurs).
# 'publish_generated_columns' is set to 'none' (to confirm existing default
# behavior), and is set to 'stored' (to confirm replication occurs).
#
# The test environment is set up as follows:
#
# - 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.
# pub2 has publish_generated_columns=true.
# pub2 has publish_generated_columns as 'stored'.
#
# - Subscription sub1 on the 'postgres' database for publication pub1.
#
@ -132,8 +132,8 @@ $node_publisher->safe_psql(
'postgres', qq(
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);
CREATE PUBLICATION regress_pub1_gen_to_nogen FOR TABLE tab_gen_to_nogen WITH (publish_generated_columns = false);
CREATE PUBLICATION regress_pub2_gen_to_nogen FOR TABLE tab_gen_to_nogen WITH (publish_generated_columns = true);
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 = stored);
));
# 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');
# 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',
"SELECT a, b FROM tab_gen_to_nogen ORDER BY a");
is( $result, qq(1|
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
# when publish_generated_columns is set to true.
# when publish_generated_columns is set to 'stored'.
$result = $node_subscriber->safe_psql('test_pgc_true',
"SELECT a, b FROM tab_gen_to_nogen ORDER BY a");
is( $result, qq(1|2
2|4
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.
$node_publisher->safe_psql('postgres',
"INSERT INTO tab_gen_to_nogen VALUES (4), (5)");
# 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');
$result = $node_subscriber->safe_psql('postgres',
"SELECT a, b FROM tab_gen_to_nogen ORDER BY a");
@ -187,11 +187,11 @@ is( $result, qq(1|
3|
4|
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
# 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');
$result = $node_subscriber->safe_psql('test_pgc_true',
"SELECT a, b FROM tab_gen_to_nogen ORDER BY a");
@ -200,7 +200,7 @@ is( $result, qq(1|2
3|6
4|8
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
@ -221,15 +221,16 @@ $node_subscriber->safe_psql('postgres', "DROP DATABASE test_pgc_true");
# with the publication parameter 'publish_generated_columns'.
#
# 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
# 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,
# 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.
@ -237,7 +238,7 @@ $node_publisher->safe_psql(
'postgres', qq(
CREATE TABLE tab2 (a int, gen1 int GENERATED ALWAYS AS (a * 2) STORED);
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.
@ -250,19 +251,19 @@ $node_subscriber->safe_psql(
# Wait for initial sync.
$node_subscriber->wait_for_subscription_sync($node_publisher, 'sub1');
# Initial sync test when publish_generated_columns=false.
# Verify 'gen1' is replicated regardless of the false parameter value.
# Initial sync test when publish_generated_columns is 'none'.
# Verify 'gen1' is replicated regardless of the 'none' parameter value.
$result =
$node_subscriber->safe_psql('postgres', "SELECT * FROM tab2 ORDER BY gen1");
is( $result, qq(|2
|4),
'tab2 initial sync, when publish_generated_columns=false');
'tab2 initial sync, when publish_generated_columns=none');
# Insert data to verify incremental replication.
$node_publisher->safe_psql('postgres', "INSERT INTO tab2 VALUES (3), (4)");
# Incremental replication test when publish_generated_columns=false.
# Verify 'gen1' is replicated regardless of the false parameter value.
# Incremental replication test when publish_generated_columns is 'none'.
# Verify 'gen1' is replicated regardless of the 'none' parameter value.
$node_publisher->wait_for_catchup('sub1');
$result =
$node_subscriber->safe_psql('postgres', "SELECT * FROM tab2 ORDER BY gen1");
@ -270,15 +271,15 @@ is( $result, qq(|2
|4
|6
|8),
'tab2 incremental replication, when publish_generated_columns=false');
'tab2 incremental replication, when publish_generated_columns=none');
# cleanup
$node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION sub1");
$node_publisher->safe_psql('postgres', "DROP PUBLICATION pub1");
# --------------------------------------------------
# Test Case: Even when publish_generated_columns is set to true, the publisher
# only publishes the data of columns specified in the column list,
# Test Case: Even when publish_generated_columns is set to 'stored', the
# publisher only publishes the data of columns specified in the column list,
# skipping other generated and non-generated columns.
# --------------------------------------------------
@ -287,7 +288,7 @@ $node_publisher->safe_psql(
'postgres', qq(
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);
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.
@ -300,19 +301,19 @@ $node_subscriber->safe_psql(
# Wait for initial sync.
$node_subscriber->wait_for_subscription_sync($node_publisher, 'sub1');
# Initial sync test when publish_generated_columns=true.
# Verify only 'gen1' is replicated regardless of the true parameter value.
# Initial sync test when publish_generated_columns is 'stored'.
# Verify only 'gen1' is replicated regardless of the 'stored' parameter value.
$result =
$node_subscriber->safe_psql('postgres', "SELECT * FROM tab3 ORDER BY gen1");
is( $result, qq(|2|
|4|),
'tab3 initial sync, when publish_generated_columns=true');
'tab3 initial sync, when publish_generated_columns=stored');
# Insert data to verify incremental replication.
$node_publisher->safe_psql('postgres', "INSERT INTO tab3 VALUES (3), (4)");
# Incremental replication test when publish_generated_columns=true.
# Verify only 'gen1' is replicated regardless of the true parameter value.
# Incremental replication test when publish_generated_columns is 'stored'.
# Verify only 'gen1' is replicated regardless of the 'stored' parameter value.
$node_publisher->wait_for_catchup('sub1');
$result =
$node_subscriber->safe_psql('postgres', "SELECT * FROM tab3 ORDER BY gen1");
@ -320,7 +321,7 @@ is( $result, qq(|2|
|4|
|6|
|8|),
'tab3 incremental replication, when publish_generated_columns=true');
'tab3 incremental replication, when publish_generated_columns=stored');
# cleanup
$node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION sub1");

View File

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