On Thu, Sep 16, 2021 at 8:45 AM Amit Kapila <[email protected]> wrote:
>
> On Wed, Sep 15, 2021 at 6:06 PM Alvaro Herrera <[email protected]>
> wrote:
> >
> > On 2021-Sep-15, vignesh C wrote:
> > > The patch
> > > Generic_object_type_parser_002_table_schema_publication.patch has the
> > > changes that were used to handle the parsing. Schema and Relation both
> > > are different objects, schema is of string type and relation is of
> > > RangeVar type. While parsing, schema name is parsed in string format
> > > and relation is parsed and converted to rangevar type, these objects
> > > will be then handled accordingly during post processing.
> >
> > Yeah, I think it'd be cleaner if the node type has two members, something
> > like
> > this
> >
> > typedef struct PublicationObjSpec
> > {
> > NodeTag type;
> > PublicationObjSpecType pubobjtype; /* type of this publication
> > object */
> > RangeVar *rv; /* if a table */
> > String *objname; /* if a schema */
> > int location; /* token location, or -1 if
> > unknown */
> > } PublicationObjSpec;
> >
> > and only one of them is set, the other is NULL, depending on the object
> > type.
> >
>
> I think the problem here is that with the proposed grammar we won't be
> always able to distinguish names at the gram.y stage.
This is the issue that Amit was talking about:
gram.y: error: shift/reduce conflicts: 2 found, 0 expected
gram.y: warning: shift/reduce conflict on token ',' [-Wcounterexamples]
First example: CREATE PUBLICATION name FOR TABLE relation_expr_list
• ',' relation_expr ',' PublicationObjSpec opt_definition $end
Shift derivation
$accept
↳ parse_toplevel
$end
↳ stmtmulti
↳ toplevel_stmt
↳ stmt
↳ CreatePublicationStmt
↳ CREATE PUBLICATION name FOR pub_obj_list
opt_definition
↳ PublicationObjSpec
',' PublicationObjSpec
↳ TABLE relation_expr_list
↳
relation_expr_list • ',' relation_expr
Second example: CREATE PUBLICATION name FOR TABLE relation_expr_list
• ',' PublicationObjSpec opt_definition $end
Reduce derivation
$accept
↳ parse_toplevel
$end
↳ stmtmulti
↳ toplevel_stmt
↳ stmt
↳ CreatePublicationStmt
↳ CREATE PUBLICATION name FOR pub_obj_list
opt_definition
↳ pub_obj_list
',' PublicationObjSpec
↳ PublicationObjSpec
↳ TABLE relation_expr_list •
Here it is not able to distinguish if ',' is used for the next table
name or the next object.
I was able to reproduce this issue with the attached patch.
Regards,
Vignesh
diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c
index d6fddd6efe..2a2fe03c13 100644
--- a/src/backend/catalog/pg_publication.c
+++ b/src/backend/catalog/pg_publication.c
@@ -141,14 +141,14 @@ pg_relation_is_publishable(PG_FUNCTION_ARGS)
* Insert new publication / relation mapping.
*/
ObjectAddress
-publication_add_relation(Oid pubid, PublicationRelInfo *targetrel,
+publication_add_relation(Oid pubid, Relation targetrel,
bool if_not_exists)
{
Relation rel;
HeapTuple tup;
Datum values[Natts_pg_publication_rel];
bool nulls[Natts_pg_publication_rel];
- Oid relid = RelationGetRelid(targetrel->relation);
+ Oid relid = RelationGetRelid(targetrel);
Oid prrelid;
Publication *pub = GetPublication(pubid);
ObjectAddress myself,
@@ -172,10 +172,10 @@ publication_add_relation(Oid pubid, PublicationRelInfo *targetrel,
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("relation \"%s\" is already member of publication \"%s\"",
- RelationGetRelationName(targetrel->relation), pub->name)));
+ RelationGetRelationName(targetrel), pub->name)));
}
- check_publication_add_relation(targetrel->relation);
+ check_publication_add_relation(targetrel);
/* Form a tuple. */
memset(values, 0, sizeof(values));
@@ -209,7 +209,7 @@ publication_add_relation(Oid pubid, PublicationRelInfo *targetrel,
table_close(rel, RowExclusiveLock);
/* Invalidate relcache so that publication info is rebuilt. */
- CacheInvalidateRelcache(targetrel->relation);
+ CacheInvalidateRelcache(targetrel);
return myself;
}
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 30929da1f5..4e4e02ba70 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -34,6 +34,7 @@
#include "commands/publicationcmds.h"
#include "funcapi.h"
#include "miscadmin.h"
+#include "nodes/makefuncs.h"
#include "utils/acl.h"
#include "utils/array.h"
#include "utils/builtins.h"
@@ -138,6 +139,85 @@ parse_publication_options(ParseState *pstate,
}
}
+/*
+ * Convert the PublicationObjSpecType list into schema oid list and rangevar
+ * list.
+ */
+static void
+ObjectsInPublicationToOids(List *pubobjspec_list, ParseState *pstate,
+ List **rels, List **schemas)
+{
+ ListCell *cell;
+ PublicationObjSpec *pubobj;
+ PublicationObjSpecType prevobjtype = PUBLICATIONOBJ_UNKNOWN;
+
+ if (!pubobjspec_list)
+ return;
+
+ pubobj = (PublicationObjSpec *) linitial(pubobjspec_list);
+ if (pubobj->pubobjtype == PUBLICATIONOBJ_UNKNOWN)
+ ereport(ERROR,
+ errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("FOR TABLE/FOR ALL TABLES IN SCHEMA should be specified before the table/schema name(s)"),
+ parser_errposition(pstate, pubobj->location));
+
+ foreach(cell, pubobjspec_list)
+ {
+ Node *node;
+
+ pubobj = (PublicationObjSpec *) lfirst(cell);
+ node = (Node *) pubobj->object;
+
+ if (pubobj->pubobjtype == PUBLICATIONOBJ_UNKNOWN)
+ pubobj->pubobjtype = prevobjtype;
+ else
+ prevobjtype = pubobj->pubobjtype;
+
+ if (pubobj->pubobjtype == PUBLICATIONOBJ_TABLE)
+ {
+ if (IsA(node, RangeVar))
+ *rels = lappend(*rels, (RangeVar *) node);
+ else if (IsA(node, String))
+ {
+ RangeVar *rel = makeRangeVar(NULL, strVal(node),
+ pubobj->location);
+ *rels = lappend(*rels, rel);
+ }
+ }
+ else if (pubobj->pubobjtype == PUBLICATIONOBJ_REL_IN_SCHEMA)
+ {
+ Oid schemaid;
+ char *schemaname;
+
+ if (!IsA(node, String))
+ ereport(ERROR,
+ errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("invalid schema name at or near"),
+ parser_errposition(pstate, pubobj->location));
+
+ schemaname = strVal(node);
+ if (strcmp(schemaname, "CURRENT_SCHEMA") == 0)
+ {
+ List *search_path;
+
+ search_path = fetch_search_path(false);
+ if (search_path == NIL) /* nothing valid in search_path? */
+ ereport(ERROR,
+ errcode(ERRCODE_UNDEFINED_SCHEMA),
+ errmsg("no schema has been selected for CURRENT_SCHEMA"));
+
+ schemaid = linitial_oid(search_path);
+ list_free(search_path);
+ }
+ else
+ schemaid = get_namespace_oid(schemaname, false);
+
+ /* Filter out duplicates if user specifies "sch1, sch1" */
+ *schemas = list_append_unique_oid(*schemas, schemaid);
+ }
+ }
+}
+
/*
* Create new publication.
*/
@@ -155,6 +235,8 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
bool publish_via_partition_root_given;
bool publish_via_partition_root;
AclResult aclresult;
+ List *relations = NIL;
+ List *schemaidlist = NIL;
/* must have CREATE privilege on database */
aclresult = pg_database_aclcheck(MyDatabaseId, GetUserId(), ACL_CREATE);
@@ -224,13 +306,15 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
/* Make the changes visible. */
CommandCounterIncrement();
- if (stmt->tables)
+ ObjectsInPublicationToOids(stmt->pubobjects, pstate, &relations,
+ &schemaidlist);
+ if (relations != NIL)
{
List *rels;
- Assert(list_length(stmt->tables) > 0);
+ Assert(list_length(relations) > 0);
- rels = OpenTableList(stmt->tables);
+ rels = OpenTableList(relations);
PublicationAddTables(puboid, rels, true, NULL);
CloseTableList(rels);
}
@@ -360,7 +444,7 @@ AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt,
*/
static void
AlterPublicationTables(AlterPublicationStmt *stmt, Relation rel,
- HeapTuple tup)
+ HeapTuple tup, List *tables, List *schemaidlist)
{
List *rels = NIL;
Form_pg_publication pubform = (Form_pg_publication) GETSTRUCT(tup);
@@ -374,13 +458,13 @@ AlterPublicationTables(AlterPublicationStmt *stmt, Relation rel,
NameStr(pubform->pubname)),
errdetail("Tables cannot be added to or dropped from FOR ALL TABLES publications.")));
- Assert(list_length(stmt->tables) > 0);
+ Assert(list_length(tables) > 0);
- rels = OpenTableList(stmt->tables);
+ rels = OpenTableList(tables);
- if (stmt->tableAction == DEFELEM_ADD)
+ if (stmt->action == DEFELEM_ADD)
PublicationAddTables(pubid, rels, false, stmt);
- else if (stmt->tableAction == DEFELEM_DROP)
+ else if (stmt->action == DEFELEM_DROP)
PublicationDropTables(pubid, rels, false);
else /* DEFELEM_SET */
{
@@ -398,10 +482,9 @@ AlterPublicationTables(AlterPublicationStmt *stmt, Relation rel,
foreach(newlc, rels)
{
- PublicationRelInfo *newpubrel;
+ Relation newrel = (Relation) lfirst(newlc);
- newpubrel = (PublicationRelInfo *) lfirst(newlc);
- if (RelationGetRelid(newpubrel->relation) == oldrelid)
+ if (RelationGetRelid(newrel) == oldrelid)
{
found = true;
break;
@@ -410,16 +493,10 @@ AlterPublicationTables(AlterPublicationStmt *stmt, Relation rel,
/* Not yet in the list, open it and add to the list */
if (!found)
{
- Relation oldrel;
- PublicationRelInfo *pubrel;
-
- /* Wrap relation into PublicationRelInfo */
- oldrel = table_open(oldrelid, ShareUpdateExclusiveLock);
+ Relation oldrel = table_open(oldrelid,
+ ShareUpdateExclusiveLock);
- pubrel = palloc(sizeof(PublicationRelInfo));
- pubrel->relation = oldrel;
-
- delrels = lappend(delrels, pubrel);
+ delrels = lappend(delrels, oldrel);
}
}
@@ -450,6 +527,8 @@ AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt)
Relation rel;
HeapTuple tup;
Form_pg_publication pubform;
+ List *relations = NIL;
+ List *schemaidlist = NIL;
rel = table_open(PublicationRelationId, RowExclusiveLock);
@@ -469,10 +548,16 @@ AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt)
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_PUBLICATION,
stmt->pubname);
+ ObjectsInPublicationToOids(stmt->pubobjects, pstate, &relations,
+ &schemaidlist);
+
if (stmt->options)
AlterPublicationOptions(pstate, stmt, rel, tup);
else
- AlterPublicationTables(stmt, rel, tup);
+ {
+ if (relations)
+ AlterPublicationTables(stmt, rel, tup, relations, schemaidlist);
+ }
/* Cleanup. */
heap_freetuple(tup);
@@ -540,7 +625,7 @@ RemovePublicationById(Oid pubid)
/*
* Open relations specified by a PublicationTable list.
- * In the returned list of PublicationRelInfo, tables are locked
+ * In the returned list of Relation, tables are locked
* in ShareUpdateExclusiveLock mode in order to add them to a publication.
*/
static List *
@@ -555,16 +640,15 @@ OpenTableList(List *tables)
*/
foreach(lc, tables)
{
- PublicationTable *t = lfirst_node(PublicationTable, lc);
- bool recurse = t->relation->inh;
+ RangeVar *rv = lfirst_node(RangeVar, lc);
+ bool recurse = rv->inh;
Relation rel;
Oid myrelid;
- PublicationRelInfo *pub_rel;
/* Allow query cancel in case this takes a long time */
CHECK_FOR_INTERRUPTS();
- rel = table_openrv(t->relation, ShareUpdateExclusiveLock);
+ rel = table_openrv(rv, ShareUpdateExclusiveLock);
myrelid = RelationGetRelid(rel);
/*
@@ -580,9 +664,7 @@ OpenTableList(List *tables)
continue;
}
- pub_rel = palloc(sizeof(PublicationRelInfo));
- pub_rel->relation = rel;
- rels = lappend(rels, pub_rel);
+ rels = lappend(rels, rel);
relids = lappend_oid(relids, myrelid);
/*
@@ -615,9 +697,7 @@ OpenTableList(List *tables)
/* find_all_inheritors already got lock */
rel = table_open(childrelid, NoLock);
- pub_rel = palloc(sizeof(PublicationRelInfo));
- pub_rel->relation = rel;
- rels = lappend(rels, pub_rel);
+ rels = lappend(rels, rel);
relids = lappend_oid(relids, childrelid);
}
}
@@ -638,10 +718,9 @@ CloseTableList(List *rels)
foreach(lc, rels)
{
- PublicationRelInfo *pub_rel;
+ Relation rel = (Relation) lfirst(lc);
- pub_rel = (PublicationRelInfo *) lfirst(lc);
- table_close(pub_rel->relation, NoLock);
+ table_close(rel, NoLock);
}
}
@@ -658,8 +737,7 @@ PublicationAddTables(Oid pubid, List *rels, bool if_not_exists,
foreach(lc, rels)
{
- PublicationRelInfo *pub_rel = (PublicationRelInfo *) lfirst(lc);
- Relation rel = pub_rel->relation;
+ Relation rel = (Relation) lfirst(lc);
ObjectAddress obj;
/* Must be owner of the table or superuser. */
@@ -667,7 +745,7 @@ PublicationAddTables(Oid pubid, List *rels, bool if_not_exists,
aclcheck_error(ACLCHECK_NOT_OWNER, get_relkind_objtype(rel->rd_rel->relkind),
RelationGetRelationName(rel));
- obj = publication_add_relation(pubid, pub_rel, if_not_exists);
+ obj = publication_add_relation(pubid, rel, if_not_exists);
if (stmt)
{
EventTriggerCollectSimpleCommand(obj, InvalidObjectAddress,
@@ -691,8 +769,7 @@ PublicationDropTables(Oid pubid, List *rels, bool missing_ok)
foreach(lc, rels)
{
- PublicationRelInfo *pubrel = (PublicationRelInfo *) lfirst(lc);
- Relation rel = pubrel->relation;
+ Relation rel = (Relation) lfirst(lc);
Oid relid = RelationGetRelid(rel);
prid = GetSysCacheOid2(PUBLICATIONRELMAP, Anum_pg_publication_rel_oid,
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 228387eaee..ade93023b8 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -4817,7 +4817,7 @@ _copyCreatePublicationStmt(const CreatePublicationStmt *from)
COPY_STRING_FIELD(pubname);
COPY_NODE_FIELD(options);
- COPY_NODE_FIELD(tables);
+ COPY_NODE_FIELD(pubobjects);
COPY_SCALAR_FIELD(for_all_tables);
return newnode;
@@ -4830,9 +4830,9 @@ _copyAlterPublicationStmt(const AlterPublicationStmt *from)
COPY_STRING_FIELD(pubname);
COPY_NODE_FIELD(options);
- COPY_NODE_FIELD(tables);
+ COPY_NODE_FIELD(pubobjects);
COPY_SCALAR_FIELD(for_all_tables);
- COPY_SCALAR_FIELD(tableAction);
+ COPY_SCALAR_FIELD(action);
return newnode;
}
@@ -4958,12 +4958,14 @@ _copyForeignKeyCacheInfo(const ForeignKeyCacheInfo *from)
return newnode;
}
-static PublicationTable *
-_copyPublicationTable(const PublicationTable *from)
+static PublicationObjSpec *
+_copyPublicationObject(const PublicationObjSpec *from)
{
- PublicationTable *newnode = makeNode(PublicationTable);
+ PublicationObjSpec *newnode = makeNode(PublicationObjSpec);
- COPY_NODE_FIELD(relation);
+ COPY_SCALAR_FIELD(pubobjtype);
+ COPY_NODE_FIELD(object);
+ COPY_LOCATION_FIELD(location);
return newnode;
}
@@ -5887,8 +5889,8 @@ copyObjectImpl(const void *from)
case T_PartitionCmd:
retval = _copyPartitionCmd(from);
break;
- case T_PublicationTable:
- retval = _copyPublicationTable(from);
+ case T_PublicationObjSpec:
+ retval = _copyPublicationObject(from);
break;
/*
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 800f588b5c..d384af2db7 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -2302,7 +2302,7 @@ _equalCreatePublicationStmt(const CreatePublicationStmt *a,
{
COMPARE_STRING_FIELD(pubname);
COMPARE_NODE_FIELD(options);
- COMPARE_NODE_FIELD(tables);
+ COMPARE_NODE_FIELD(pubobjects);
COMPARE_SCALAR_FIELD(for_all_tables);
return true;
@@ -2314,9 +2314,9 @@ _equalAlterPublicationStmt(const AlterPublicationStmt *a,
{
COMPARE_STRING_FIELD(pubname);
COMPARE_NODE_FIELD(options);
- COMPARE_NODE_FIELD(tables);
+ COMPARE_NODE_FIELD(pubobjects);
COMPARE_SCALAR_FIELD(for_all_tables);
- COMPARE_SCALAR_FIELD(tableAction);
+ COMPARE_SCALAR_FIELD(action);
return true;
}
@@ -3134,12 +3134,12 @@ _equalBitString(const BitString *a, const BitString *b)
}
static bool
-_equalPublicationTable(const PublicationTable *a, const PublicationTable *b)
+_equalPublicationObject(const PublicationObjSpec *a, const PublicationObjSpec *b)
{
- COMPARE_NODE_FIELD(relation);
+ COMPARE_NODE_FIELD(object);
return true;
-}
+}
/*
* equal
@@ -3894,8 +3894,8 @@ equal(const void *a, const void *b)
case T_PartitionCmd:
retval = _equalPartitionCmd(a, b);
break;
- case T_PublicationTable:
- retval = _equalPublicationTable(a, b);
+ case T_PublicationObjSpec:
+ retval = _equalPublicationObject(a, b);
break;
default:
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index e3068a374e..c50bb570ea 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -256,6 +256,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
PartitionSpec *partspec;
PartitionBoundSpec *partboundspec;
RoleSpec *rolespec;
+ PublicationObjSpec *publicationobjectspec;
struct SelectLimit *selectlimit;
SetQuantifier setquantifier;
struct GroupClause *groupclause;
@@ -425,14 +426,13 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
transform_element_list transform_type_list
TriggerTransitions TriggerReferencing
vacuum_relation_list opt_vacuum_relation_list
- drop_option_list publication_table_list
+ drop_option_list pub_obj_list pubobj_expr_list
%type <node> opt_routine_body
%type <groupclause> group_clause
%type <list> group_by_list
%type <node> group_by_item empty_grouping_set rollup_clause cube_clause
%type <node> grouping_sets_clause
-%type <node> opt_publication_for_tables publication_for_tables publication_table
%type <list> opt_fdw_options fdw_options
%type <defelt> fdw_option
@@ -554,6 +554,9 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <node> var_value zone_value
%type <rolespec> auth_ident RoleSpec opt_granted_by
+%type <publicationobjectspec> PublicationObjSpec
+%type <publicationobjectspec> pubobj_expr
+%type <node> pubobj_name
%type <keyword> unreserved_keyword type_func_name_keyword
%type <keyword> col_name_keyword reserved_keyword
%type <keyword> bare_label_keyword
@@ -9591,69 +9594,107 @@ AlterOwnerStmt: ALTER AGGREGATE aggregate_with_argtypes OWNER TO RoleSpec
/*****************************************************************************
*
- * CREATE PUBLICATION name [ FOR TABLE ] [ WITH options ]
+ * CREATE PUBLICATION name [WITH options]
+ *
+ * CREATE PUBLICATION FOR ALL TABLES [WITH options]
+ *
+ * CREATE PUBLICATION FOR pub_obj [, pub_obj2] [WITH options]
+ *
+ * pub_obj is one of:
+ *
+ * TABLE table [, table2]
+ * ALL TABLES IN SCHEMA schema [, schema2]
*
*****************************************************************************/
CreatePublicationStmt:
- CREATE PUBLICATION name opt_publication_for_tables opt_definition
+ CREATE PUBLICATION name opt_definition
{
CreatePublicationStmt *n = makeNode(CreatePublicationStmt);
n->pubname = $3;
- n->options = $5;
- if ($4 != NULL)
- {
- /* FOR TABLE */
- if (IsA($4, List))
- n->tables = (List *)$4;
- /* FOR ALL TABLES */
- else
- n->for_all_tables = true;
- }
+ n->options = $4;
+ $$ = (Node *)n;
+ }
+ | CREATE PUBLICATION name FOR ALL TABLES opt_definition
+ {
+ CreatePublicationStmt *n = makeNode(CreatePublicationStmt);
+ n->pubname = $3;
+ n->options = $7;
+ n->for_all_tables = true;
+ $$ = (Node *)n;
+ }
+ | CREATE PUBLICATION name FOR pub_obj_list opt_definition
+ {
+ CreatePublicationStmt *n = makeNode(CreatePublicationStmt);
+ n->pubname = $3;
+ n->options = $6;
+ n->pubobjects = (List *)$5;
$$ = (Node *)n;
}
;
-opt_publication_for_tables:
- publication_for_tables { $$ = $1; }
- | /* EMPTY */ { $$ = NULL; }
+pubobj_expr:
+ pubobj_name
+ {
+ /* inheritance query, implicitly */
+ $$ = makeNode(PublicationObjSpec);
+ $$->object = $1;
+ }
;
-publication_for_tables:
- FOR TABLE publication_table_list
+/* This can be either a schema or relation name. */
+pubobj_name:
+ ColId
{
- $$ = (Node *) $3;
+ $$ = (Node *) makeString($1);
}
- | FOR ALL TABLES
+ | ColId indirection
{
- $$ = (Node *) makeInteger(true);
+ $$ = (Node *) makeRangeVarFromQualifiedName($1, $2, @1, yyscanner);
}
;
-publication_table_list:
- publication_table
- { $$ = list_make1($1); }
- | publication_table_list ',' publication_table
- { $$ = lappend($1, $3); }
+/* FOR TABLE and FOR ALL TABLES IN SCHEMA specifications */
+PublicationObjSpec: TABLE relation_expr_list
+ {
+ $$ = $2;
+ $$->pubobjtype = PUBLICATIONOBJ_TABLE;
+ $$->location = @1;
+ }
+ | ALL TABLES IN_P SCHEMA pubobj_expr_list
+ {
+ $$ = $5;
+ $$->pubobjtype = PUBLICATIONOBJ_REL_IN_SCHEMA;
+ $$->location = @1;
+ }
;
-publication_table: relation_expr
- {
- PublicationTable *n = makeNode(PublicationTable);
- n->relation = $1;
- $$ = (Node *) n;
- }
+pubobj_expr_list: pubobj_expr
+ { $$ = list_make1($1); }
+ | pubobj_expr_list ',' pubobj_expr
+ { $$ = lappend($1, $3); }
+ ;
+
+pub_obj_list: PublicationObjSpec
+ { $$ = list_make1($1); }
+ | pub_obj_list ',' PublicationObjSpec
+ { $$ = lappend($1, $3); }
;
/*****************************************************************************
*
* ALTER PUBLICATION name SET ( options )
*
- * ALTER PUBLICATION name ADD TABLE table [, table2]
+ * ALTER PUBLICATION name ADD pub_obj [, pub_obj ...]
+ *
+ * ALTER PUBLICATION name DROP pub_obj [, pub_obj ...]
+ *
+ * ALTER PUBLICATION name SET pub_obj [, pub_obj ...]
*
- * ALTER PUBLICATION name DROP TABLE table [, table2]
+ * pub_obj is one of:
*
- * ALTER PUBLICATION name SET TABLE table [, table2]
+ * TABLE table_name [, table_name ...]
+ * ALL TABLES IN SCHEMA schema_name [, schema_name ...]
*
*****************************************************************************/
@@ -9665,28 +9706,28 @@ AlterPublicationStmt:
n->options = $5;
$$ = (Node *)n;
}
- | ALTER PUBLICATION name ADD_P TABLE publication_table_list
+ | ALTER PUBLICATION name ADD_P pub_obj_list
{
AlterPublicationStmt *n = makeNode(AlterPublicationStmt);
n->pubname = $3;
- n->tables = $6;
- n->tableAction = DEFELEM_ADD;
+ n->pubobjects = $5;
+ n->action = DEFELEM_ADD;
$$ = (Node *)n;
}
- | ALTER PUBLICATION name SET TABLE publication_table_list
+ | ALTER PUBLICATION name SET pub_obj_list
{
AlterPublicationStmt *n = makeNode(AlterPublicationStmt);
n->pubname = $3;
- n->tables = $6;
- n->tableAction = DEFELEM_SET;
+ n->pubobjects = $5;
+ n->action = DEFELEM_SET;
$$ = (Node *)n;
}
- | ALTER PUBLICATION name DROP TABLE publication_table_list
+ | ALTER PUBLICATION name DROP pub_obj_list
{
AlterPublicationStmt *n = makeNode(AlterPublicationStmt);
n->pubname = $3;
- n->tables = $6;
- n->tableAction = DEFELEM_DROP;
+ n->pubobjects = $5;
+ n->action = DEFELEM_DROP;
$$ = (Node *)n;
}
;
diff --git a/src/include/catalog/pg_publication.h b/src/include/catalog/pg_publication.h
index 561266aa3e..f332bad4d4 100644
--- a/src/include/catalog/pg_publication.h
+++ b/src/include/catalog/pg_publication.h
@@ -83,11 +83,6 @@ typedef struct Publication
PublicationActions pubactions;
} Publication;
-typedef struct PublicationRelInfo
-{
- Relation relation;
-} PublicationRelInfo;
-
extern Publication *GetPublication(Oid pubid);
extern Publication *GetPublicationByName(const char *pubname, bool missing_ok);
extern List *GetRelationPublications(Oid relid);
@@ -113,7 +108,7 @@ extern List *GetAllTablesPublications(void);
extern List *GetAllTablesPublicationRelations(bool pubviaroot);
extern bool is_publishable_relation(Relation rel);
-extern ObjectAddress publication_add_relation(Oid pubid, PublicationRelInfo *targetrel,
+extern ObjectAddress publication_add_relation(Oid pubid, Relation targetrel,
bool if_not_exists);
extern Oid get_publication_oid(const char *pubname, bool missing_ok);
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index e0057daa06..d34b4ac8e5 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -487,7 +487,7 @@ typedef enum NodeTag
T_PartitionRangeDatum,
T_PartitionCmd,
T_VacuumRelation,
- T_PublicationTable,
+ T_PublicationObjSpec,
/*
* TAGS FOR REPLICATION GRAMMAR PARSE NODES (replnodes.h)
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 3138877553..20eeb12022 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -353,6 +353,26 @@ typedef struct RoleSpec
int location; /* token location, or -1 if unknown */
} RoleSpec;
+/*
+ * Publication object type
+ */
+typedef enum PublicationObjSpecType
+{
+ PUBLICATIONOBJ_TABLE, /* Table type */
+ PUBLICATIONOBJ_REL_IN_SCHEMA, /* Relations in schema type */
+ PUBLICATIONOBJ_UNKNOWN /* Unknown type */
+} PublicationObjSpecType;
+
+typedef struct PublicationObjSpec
+{
+ NodeTag type;
+ PublicationObjSpecType pubobjtype; /* type of this publication object */
+ void *object; /* publication object could be:
+ * RangeVar - table object
+ * String - tablename or schemaname */
+ int location; /* token location, or -1 if unknown */
+} PublicationObjSpec;
+
/*
* FuncCall - a function or aggregate invocation
*
@@ -3636,18 +3656,12 @@ typedef struct AlterTSConfigurationStmt
bool missing_ok; /* for DROP - skip error if missing? */
} AlterTSConfigurationStmt;
-typedef struct PublicationTable
-{
- NodeTag type;
- RangeVar *relation; /* relation to be published */
-} PublicationTable;
-
typedef struct CreatePublicationStmt
{
NodeTag type;
char *pubname; /* Name of the publication */
List *options; /* List of DefElem nodes */
- List *tables; /* Optional list of tables to add */
+ List *pubobjects; /* Optional list of publication objects */
bool for_all_tables; /* Special publication for all tables in db */
} CreatePublicationStmt;
@@ -3659,10 +3673,11 @@ typedef struct AlterPublicationStmt
/* parameters used for ALTER PUBLICATION ... WITH */
List *options; /* List of DefElem nodes */
- /* parameters used for ALTER PUBLICATION ... ADD/DROP TABLE */
- List *tables; /* List of tables to add/drop */
+ /* ALTER PUBLICATION ... ADD/DROP TABLE/ALL TABLES IN SCHEMA parameters */
+ List *pubobjects; /* Optional list of publication objects */
bool for_all_tables; /* Special publication for all tables in db */
- DefElemAction tableAction; /* What action to perform with the tables */
+ DefElemAction action; /* What action to perform with the
+ * tables/schemas */
} AlterPublicationStmt;
typedef struct CreateSubscriptionStmt
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 423780652f..8a1b97836e 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2045,8 +2045,9 @@ PsqlSettings
Publication
PublicationActions
PublicationInfo
+PublicationObjSpec
+PublicationObjSpecType
PublicationPartOpt
-PublicationRelInfo
PublicationTable
PullFilter
PullFilterOps