]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Change publication's publish_generated_columns option type to enum.
authorAmit Kapila <akapila@postgresql.org>
Thu, 23 Jan 2025 09:58:37 +0000 (15:28 +0530)
committerAmit Kapila <akapila@postgresql.org>
Thu, 23 Jan 2025 09:58:37 +0000 (15:28 +0530)
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

19 files changed:
doc/src/sgml/catalogs.sgml
doc/src/sgml/ref/create_publication.sgml
src/backend/catalog/pg_publication.c
src/backend/commands/publicationcmds.c
src/backend/replication/logical/proto.c
src/backend/replication/pgoutput/pgoutput.c
src/backend/utils/cache/relcache.c
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_dump.h
src/bin/pg_dump/t/002_pg_dump.pl
src/bin/psql/describe.c
src/include/catalog/catversion.h
src/include/catalog/pg_publication.h
src/include/commands/publicationcmds.h
src/include/replication/logicalproto.h
src/test/regress/expected/publication.out
src/test/regress/sql/publication.sql
src/test/subscription/t/011_generated.pl
src/tools/pgindent/typedefs.list

index d3036c5ba9d609dac80737fd3c009d16be933e4c..c88bcaa7df9566de40c784326c0d8610ae63d071 100644 (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>
index 5e25536554a897db4d13333455520c31b3898227..e822ea2aaa9a3dfe4ae5b0d2e1dcb466965b1df7 100644 (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>
index b89098f5e99aac92320da4491ee64fd4a19612e2..7900a8f6a1338107bc8f3a4f38fcfce09d0a0ae7 100644 (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;
                        }
 
index 35747b3df5f2d9942d734a7bb7dae5b8b918068f..b49d9ab78bf588b5f17e5afaa19062be2e6efde5 100644 (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 */
+}
index bef350714dbae9910ce8b140f68f13eb7826f627..dc72b7c8f77a9c85eed0051ff215cf3b7177c4cb 100644 (file)
 #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;
 }
index 2b7499b34b91525c9d764a90f67ffedcf0978e8a..a363c88ffc033623c7f47f93a8988d4f8ccc5041 100644 (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);
index 43219a9629c3b83b9e627fc36693bf09e00cd491..ee39d085ebefb657b19ddf8ee8a1432b2c8a3dd6 100644 (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))
                {
index 8f73a5df9568b8706cd20b72925e49190c5d72e6..9b840fc400a18b63bd54f52958718c4e23e7e89b 100644 (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");
 
index f62b564ed1bed4f1c218a893b120d6a4923f2479..7139c88a69a10d65c2efe895503575ec1264e31b 100644 (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;
 
 /*
index a643a73270e5e99cf5170dbecd2d6f8ba1b7a824..805ba9f49fd51dd2fe185d8bb637b015f0fe9955 100644 (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, },
        },
index 8c0ad8439eb236ff4471911a5caf1c9d63977de4..2e84b61f184a42f82442e7c56fea9d85e1a5eb9c 100644 (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,
index 28de0c8334230edeec64f535d51123f56da121d5..586b83f2f4d62c1bc72895f8dd2e2a200811b986 100644 (file)
@@ -57,6 +57,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     202501171
+#define CATALOG_VERSION_NO     202501231
 
 #endif
index 3c2ae2a960c692cbff2dc5001f6bd38802adde9f..9e6cddcac4c67d76a16517b058f57f6f4e8a506e 100644 (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 */
index 170c5ce00f0fbafbeb5ce221f9f0d44f18b33b7c..e11a942ea0fd4d53b26e765574ebca69854de5e3 100644 (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);
 
index 7012247825d049b0471e0e1e317d8804bc333719..b261c60d3fa1490de38a35d28199ddffda2d2362 100644 (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 */
index c48f11f2935180fc78ea44861eab3f2a128f9676..bc3898fbe586e24654b586d6f4746526fe74585e 100644 (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)
 
index c4c21a95d0ec0aac2ca8915e09970a462e818e09..47f0329c2440e7a92c3dbb0a768eff0973db7711 100644 (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
 
index 45587371400c4627de80747872e35ed78d6e20c5..5970bb473608a3ff6de928e93dad2f9b2c7f6b24 100644 (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");
index d5aa5c295ae7893b6f6f5db67153d8f12c1b5af4..a2644a2e6535ac2ae3ae8775feb56fe3fc05abd8 100644 (file)
@@ -2276,6 +2276,7 @@ PublicationPartOpt
 PublicationRelInfo
 PublicationSchemaInfo
 PublicationTable
+PublishGencolsType
 PullFilter
 PullFilterOps
 PushFilter