5353#include "utils/syscache.h"
5454#include "utils/varlena.h"
5555
56+
5657/*
5758 * Information used to validate the columns in the row filter expression. See
5859 * contain_invalid_rfcolumn_walker for details.
@@ -76,6 +77,7 @@ static void PublicationAddSchemas(Oid pubid, List *schemas, bool if_not_exists,
7677 AlterPublicationStmt * stmt );
7778static void PublicationDropSchemas (Oid pubid , List * schemas , bool missing_ok );
7879
80+
7981static void
8082parse_publication_options (ParseState * pstate ,
8183 List * options ,
@@ -125,7 +127,8 @@ parse_publication_options(ParseState *pstate,
125127 if (!SplitIdentifierString (publish , ',' , & publish_list ))
126128 ereport (ERROR ,
127129 (errcode (ERRCODE_SYNTAX_ERROR ),
128- errmsg ("invalid list syntax for \"publish\" option" )));
130+ errmsg ("invalid list syntax in parameter \"%s\"" ,
131+ "publish" )));
129132
130133 /* Process the option list. */
131134 foreach (lc , publish_list )
@@ -143,7 +146,8 @@ parse_publication_options(ParseState *pstate,
143146 else
144147 ereport (ERROR ,
145148 (errcode (ERRCODE_SYNTAX_ERROR ),
146- errmsg ("unrecognized \"publish\" value: \"%s\"" , publish_opt )));
149+ errmsg ("unrecognized value for publication option \"%s\": \"%s\"" ,
150+ "publish" , publish_opt )));
147151 }
148152 }
149153 else if (strcmp (defel -> defname , "publish_via_partition_root" ) == 0 )
@@ -444,10 +448,12 @@ contain_mutable_or_user_functions_checker(Oid func_id, void *context)
444448}
445449
446450/*
447- * Check if the node contains any unallowed object. See
451+ * Check if the node contains any disallowed object. Subroutine for
448452 * check_simple_rowfilter_expr_walker.
449453 *
450- * Returns the error detail message in errdetail_msg for unallowed expressions.
454+ * If a disallowed object is found, *errdetail_msg is set to a (possibly
455+ * translated) message to use as errdetail. If none, *errdetail_msg is not
456+ * modified.
451457 */
452458static void
453459expr_allowed_in_node (Node * node , ParseState * pstate , char * * errdetail_msg )
@@ -678,10 +684,17 @@ TransformPubWhereClauses(List *tables, const char *queryString,
678684
679685
680686/*
681- * Check the publication column lists expression for all relations in the list.
687+ * Given a list of tables that are going to be added to a publication,
688+ * verify that they fulfill the necessary preconditions, namely: no tables
689+ * have a column list if any schema is published; and partitioned tables do
690+ * not have column lists if publish_via_partition_root is not set.
691+ *
692+ * 'publish_schema' indicates that the publication contains any TABLES IN
693+ * SCHEMA elements (newly added in this command, or preexisting).
694+ * 'pubviaroot' is the value of publish_via_partition_root.
682695 */
683696static void
684- CheckPubRelationColumnList (List * tables , const char * queryString ,
697+ CheckPubRelationColumnList (char * pubname , List * tables ,
685698 bool publish_schema , bool pubviaroot )
686699{
687700 ListCell * lc ;
@@ -706,23 +719,24 @@ CheckPubRelationColumnList(List *tables, const char *queryString,
706719 if (publish_schema )
707720 ereport (ERROR ,
708721 errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
709- errmsg ("cannot use publication column list for relation \"%s.%s\"" ,
722+ errmsg ("cannot use column list for relation \"%s.%s\" in publication \" %s\"" ,
710723 get_namespace_name (RelationGetNamespace (pri -> relation )),
711- RelationGetRelationName (pri -> relation )),
712- errdetail ("Column list cannot be specified if any schema is part of the publication or specified in the list ." ));
724+ RelationGetRelationName (pri -> relation ), pubname ),
725+ errdetail ("Column lists cannot be specified in publications containing FOR TABLES IN SCHEMA elements ." ));
713726
714727 /*
715728 * If the publication doesn't publish changes via the root partitioned
716729 * table, the partition's column list will be used. So disallow using
717- * the column list on partitioned table in this case.
730+ * a column list on the partitioned table in this case.
718731 */
719732 if (!pubviaroot &&
720733 pri -> relation -> rd_rel -> relkind == RELKIND_PARTITIONED_TABLE )
721734 ereport (ERROR ,
722735 (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
723- errmsg ("cannot use publication column list for relation \"%s\"" ,
724- RelationGetRelationName (pri -> relation )),
725- errdetail ("Column list cannot be used for a partitioned table when %s is false." ,
736+ errmsg ("cannot use column list for relation \"%s.%s\" in publication \"%s\"" ,
737+ get_namespace_name (RelationGetNamespace (pri -> relation )),
738+ RelationGetRelationName (pri -> relation ), pubname ),
739+ errdetail ("Column lists cannot be specified for partitioned tables when %s is false." ,
726740 "publish_via_partition_root" )));
727741 }
728742}
@@ -765,12 +779,10 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
765779 puboid = GetSysCacheOid1 (PUBLICATIONNAME , Anum_pg_publication_oid ,
766780 CStringGetDatum (stmt -> pubname ));
767781 if (OidIsValid (puboid ))
768- {
769782 ereport (ERROR ,
770783 (errcode (ERRCODE_DUPLICATE_OBJECT ),
771784 errmsg ("publication \"%s\" already exists" ,
772785 stmt -> pubname )));
773- }
774786
775787 /* Form a tuple. */
776788 memset (values , 0 , sizeof (values ));
@@ -840,7 +852,7 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
840852 TransformPubWhereClauses (rels , pstate -> p_sourcetext ,
841853 publish_via_partition_root );
842854
843- CheckPubRelationColumnList (rels , pstate -> p_sourcetext ,
855+ CheckPubRelationColumnList (stmt -> pubname , rels ,
844856 schemaidlist != NIL ,
845857 publish_via_partition_root );
846858
@@ -864,12 +876,10 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
864876 InvokeObjectPostCreateHook (PublicationRelationId , puboid , 0 );
865877
866878 if (wal_level != WAL_LEVEL_LOGICAL )
867- {
868879 ereport (WARNING ,
869880 (errcode (ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE ),
870881 errmsg ("wal_level is insufficient to publish logical changes" ),
871- errhint ("Set wal_level to logical before creating subscriptions." )));
872- }
882+ errhint ("Set wal_level to \"logical\" before creating subscriptions." )));
873883
874884 return myself ;
875885}
@@ -1110,7 +1120,7 @@ AlterPublicationTables(AlterPublicationStmt *stmt, HeapTuple tup,
11101120
11111121 publish_schema |= is_schema_publication (pubid );
11121122
1113- CheckPubRelationColumnList (rels , queryString , publish_schema ,
1123+ CheckPubRelationColumnList (stmt -> pubname , rels , publish_schema ,
11141124 pubform -> pubviaroot );
11151125
11161126 PublicationAddTables (pubid , rels , false, stmt );
@@ -1126,7 +1136,7 @@ AlterPublicationTables(AlterPublicationStmt *stmt, HeapTuple tup,
11261136
11271137 TransformPubWhereClauses (rels , queryString , pubform -> pubviaroot );
11281138
1129- CheckPubRelationColumnList (rels , queryString , publish_schema ,
1139+ CheckPubRelationColumnList (stmt -> pubname , rels , publish_schema ,
11301140 pubform -> pubviaroot );
11311141
11321142 /*
@@ -1299,8 +1309,9 @@ AlterPublicationSchemas(AlterPublicationStmt *stmt,
12991309 if (!heap_attisnull (coltuple , Anum_pg_publication_rel_prattrs , NULL ))
13001310 ereport (ERROR ,
13011311 errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
1302- errmsg ("cannot add schema to the publication" ),
1303- errdetail ("Schema cannot be added if any table that specifies column list is already part of the publication." ));
1312+ errmsg ("cannot add schema to publication \"%s\"" ,
1313+ stmt -> pubname ),
1314+ errdetail ("Schemas cannot be added if any tables that specify a column list are already part of the publication." ));
13041315
13051316 ReleaseSysCache (coltuple );
13061317 }
0 commit comments