1
0
mirror of https://github.com/postgres/postgres.git synced 2025-12-19 17:02:53 +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

@@ -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