On Thu, Sep 16, 2021 at 8:45 AM Amit Kapila <amit.kapil...@gmail.com> wrote: > > On Wed, Sep 15, 2021 at 6:06 PM Alvaro Herrera <alvhe...@alvh.no-ip.org> > 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