1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-11 10:01:57 +03:00

Add PublicationTable and PublicationRelInfo structs

These encapsulate a relation when referred from replication DDL.
Currently they don't do anything useful (they're just wrappers around
RangeVar and Relation respectively) but in the future they'll be used to
carry column lists.

Extracted from a larger patch by Rahila Syed.

Author: Rahila Syed <rahilasyed90@gmail.com>
Reviewed-by: Álvaro Herrera <alvherre@alvh.no-ip.org>
Reviewed-by: Tomas Vondra <tomas.vondra@enterprisedb.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Discussion: https://postgr.es/m/CAH2L28vddB_NFdRVpuyRBJEBWjz4BSyTB=_ektNRH8NJ1jf95g@mail.gmail.com
This commit is contained in:
Alvaro Herrera
2021-09-06 14:24:50 -03:00
parent 89dba59590
commit 0c6828fa98
9 changed files with 95 additions and 31 deletions

View File

@ -141,14 +141,14 @@ pg_relation_is_publishable(PG_FUNCTION_ARGS)
* Insert new publication / relation mapping. * Insert new publication / relation mapping.
*/ */
ObjectAddress ObjectAddress
publication_add_relation(Oid pubid, Relation targetrel, publication_add_relation(Oid pubid, PublicationRelInfo *targetrel,
bool if_not_exists) bool if_not_exists)
{ {
Relation rel; Relation rel;
HeapTuple tup; HeapTuple tup;
Datum values[Natts_pg_publication_rel]; Datum values[Natts_pg_publication_rel];
bool nulls[Natts_pg_publication_rel]; bool nulls[Natts_pg_publication_rel];
Oid relid = RelationGetRelid(targetrel); Oid relid = RelationGetRelid(targetrel->relation);
Oid prrelid; Oid prrelid;
Publication *pub = GetPublication(pubid); Publication *pub = GetPublication(pubid);
ObjectAddress myself, ObjectAddress myself,
@ -172,10 +172,10 @@ publication_add_relation(Oid pubid, Relation targetrel,
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT), (errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("relation \"%s\" is already member of publication \"%s\"", errmsg("relation \"%s\" is already member of publication \"%s\"",
RelationGetRelationName(targetrel), pub->name))); RelationGetRelationName(targetrel->relation), pub->name)));
} }
check_publication_add_relation(targetrel); check_publication_add_relation(targetrel->relation);
/* Form a tuple. */ /* Form a tuple. */
memset(values, 0, sizeof(values)); memset(values, 0, sizeof(values));
@ -209,7 +209,7 @@ publication_add_relation(Oid pubid, Relation targetrel,
table_close(rel, RowExclusiveLock); table_close(rel, RowExclusiveLock);
/* Invalidate relcache so that publication info is rebuilt. */ /* Invalidate relcache so that publication info is rebuilt. */
CacheInvalidateRelcache(targetrel); CacheInvalidateRelcache(targetrel->relation);
return myself; return myself;
} }

View File

@ -393,21 +393,28 @@ AlterPublicationTables(AlterPublicationStmt *stmt, Relation rel,
foreach(newlc, rels) foreach(newlc, rels)
{ {
Relation newrel = (Relation) lfirst(newlc); PublicationRelInfo *newpubrel;
if (RelationGetRelid(newrel) == oldrelid) newpubrel = (PublicationRelInfo *) lfirst(newlc);
if (RelationGetRelid(newpubrel->relation) == oldrelid)
{ {
found = true; found = true;
break; break;
} }
} }
/* Not yet in the list, open it and add to the list */
if (!found) if (!found)
{ {
Relation oldrel = table_open(oldrelid, Relation oldrel;
ShareUpdateExclusiveLock); PublicationRelInfo *pubrel;
delrels = lappend(delrels, oldrel); /* Wrap relation into PublicationRelInfo */
oldrel = table_open(oldrelid, ShareUpdateExclusiveLock);
pubrel = palloc(sizeof(PublicationRelInfo));
pubrel->relation = oldrel;
delrels = lappend(delrels, pubrel);
} }
} }
@ -498,9 +505,9 @@ RemovePublicationRelById(Oid proid)
} }
/* /*
* Open relations specified by a RangeVar list. * Open relations specified by a PublicationTable list.
* The returned tables are locked in ShareUpdateExclusiveLock mode in order to * In the returned list of PublicationRelInfo, tables are locked
* add them to a publication. * in ShareUpdateExclusiveLock mode in order to add them to a publication.
*/ */
static List * static List *
OpenTableList(List *tables) OpenTableList(List *tables)
@ -514,15 +521,16 @@ OpenTableList(List *tables)
*/ */
foreach(lc, tables) foreach(lc, tables)
{ {
RangeVar *rv = lfirst_node(RangeVar, lc); PublicationTable *t = lfirst_node(PublicationTable, lc);
bool recurse = rv->inh; bool recurse = t->relation->inh;
Relation rel; Relation rel;
Oid myrelid; Oid myrelid;
PublicationRelInfo *pub_rel;
/* Allow query cancel in case this takes a long time */ /* Allow query cancel in case this takes a long time */
CHECK_FOR_INTERRUPTS(); CHECK_FOR_INTERRUPTS();
rel = table_openrv(rv, ShareUpdateExclusiveLock); rel = table_openrv(t->relation, ShareUpdateExclusiveLock);
myrelid = RelationGetRelid(rel); myrelid = RelationGetRelid(rel);
/* /*
@ -538,7 +546,9 @@ OpenTableList(List *tables)
continue; continue;
} }
rels = lappend(rels, rel); pub_rel = palloc(sizeof(PublicationRelInfo));
pub_rel->relation = rel;
rels = lappend(rels, pub_rel);
relids = lappend_oid(relids, myrelid); relids = lappend_oid(relids, myrelid);
/* /*
@ -571,7 +581,9 @@ OpenTableList(List *tables)
/* find_all_inheritors already got lock */ /* find_all_inheritors already got lock */
rel = table_open(childrelid, NoLock); rel = table_open(childrelid, NoLock);
rels = lappend(rels, rel); pub_rel = palloc(sizeof(PublicationRelInfo));
pub_rel->relation = rel;
rels = lappend(rels, pub_rel);
relids = lappend_oid(relids, childrelid); relids = lappend_oid(relids, childrelid);
} }
} }
@ -592,9 +604,10 @@ CloseTableList(List *rels)
foreach(lc, rels) foreach(lc, rels)
{ {
Relation rel = (Relation) lfirst(lc); PublicationRelInfo *pub_rel;
table_close(rel, NoLock); pub_rel = (PublicationRelInfo *) lfirst(lc);
table_close(pub_rel->relation, NoLock);
} }
} }
@ -611,7 +624,8 @@ PublicationAddTables(Oid pubid, List *rels, bool if_not_exists,
foreach(lc, rels) foreach(lc, rels)
{ {
Relation rel = (Relation) lfirst(lc); PublicationRelInfo *pub_rel = (PublicationRelInfo *) lfirst(lc);
Relation rel = pub_rel->relation;
ObjectAddress obj; ObjectAddress obj;
/* Must be owner of the table or superuser. */ /* Must be owner of the table or superuser. */
@ -619,7 +633,7 @@ PublicationAddTables(Oid pubid, List *rels, bool if_not_exists,
aclcheck_error(ACLCHECK_NOT_OWNER, get_relkind_objtype(rel->rd_rel->relkind), aclcheck_error(ACLCHECK_NOT_OWNER, get_relkind_objtype(rel->rd_rel->relkind),
RelationGetRelationName(rel)); RelationGetRelationName(rel));
obj = publication_add_relation(pubid, rel, if_not_exists); obj = publication_add_relation(pubid, pub_rel, if_not_exists);
if (stmt) if (stmt)
{ {
EventTriggerCollectSimpleCommand(obj, InvalidObjectAddress, EventTriggerCollectSimpleCommand(obj, InvalidObjectAddress,
@ -643,7 +657,8 @@ PublicationDropTables(Oid pubid, List *rels, bool missing_ok)
foreach(lc, rels) foreach(lc, rels)
{ {
Relation rel = (Relation) lfirst(lc); PublicationRelInfo *pubrel = (PublicationRelInfo *) lfirst(lc);
Relation rel = pubrel->relation;
Oid relid = RelationGetRelid(rel); Oid relid = RelationGetRelid(rel);
prid = GetSysCacheOid2(PUBLICATIONRELMAP, Anum_pg_publication_rel_oid, prid = GetSysCacheOid2(PUBLICATIONRELMAP, Anum_pg_publication_rel_oid,

View File

@ -4939,6 +4939,15 @@ _copyForeignKeyCacheInfo(const ForeignKeyCacheInfo *from)
return newnode; return newnode;
} }
static PublicationTable *
_copyPublicationTable(const PublicationTable *from)
{
PublicationTable *newnode = makeNode(PublicationTable);
COPY_NODE_FIELD(relation);
return newnode;
}
/* /*
* copyObjectImpl -- implementation of copyObject(); see nodes/nodes.h * copyObjectImpl -- implementation of copyObject(); see nodes/nodes.h
@ -5854,6 +5863,9 @@ copyObjectImpl(const void *from)
case T_PartitionCmd: case T_PartitionCmd:
retval = _copyPartitionCmd(from); retval = _copyPartitionCmd(from);
break; break;
case T_PublicationTable:
retval = _copyPublicationTable(from);
break;
/* /*
* MISCELLANEOUS NODES * MISCELLANEOUS NODES

View File

@ -3114,6 +3114,14 @@ _equalValue(const Value *a, const Value *b)
return true; return true;
} }
static bool
_equalPublicationTable(const PublicationTable *a, const PublicationTable *b)
{
COMPARE_NODE_FIELD(relation);
return true;
}
/* /*
* equal * equal
* returns whether two nodes are equal * returns whether two nodes are equal
@ -3862,6 +3870,9 @@ equal(const void *a, const void *b)
case T_PartitionCmd: case T_PartitionCmd:
retval = _equalPartitionCmd(a, b); retval = _equalPartitionCmd(a, b);
break; break;
case T_PublicationTable:
retval = _equalPublicationTable(a, b);
break;
default: default:
elog(ERROR, "unrecognized node type: %d", elog(ERROR, "unrecognized node type: %d",

View File

@ -426,14 +426,14 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
transform_element_list transform_type_list transform_element_list transform_type_list
TriggerTransitions TriggerReferencing TriggerTransitions TriggerReferencing
vacuum_relation_list opt_vacuum_relation_list vacuum_relation_list opt_vacuum_relation_list
drop_option_list drop_option_list publication_table_list
%type <node> opt_routine_body %type <node> opt_routine_body
%type <groupclause> group_clause %type <groupclause> group_clause
%type <list> group_by_list %type <list> group_by_list
%type <node> group_by_item empty_grouping_set rollup_clause cube_clause %type <node> group_by_item empty_grouping_set rollup_clause cube_clause
%type <node> grouping_sets_clause %type <node> grouping_sets_clause
%type <node> opt_publication_for_tables publication_for_tables %type <node> opt_publication_for_tables publication_for_tables publication_table
%type <list> opt_fdw_options fdw_options %type <list> opt_fdw_options fdw_options
%type <defelt> fdw_option %type <defelt> fdw_option
@ -9620,7 +9620,7 @@ opt_publication_for_tables:
; ;
publication_for_tables: publication_for_tables:
FOR TABLE relation_expr_list FOR TABLE publication_table_list
{ {
$$ = (Node *) $3; $$ = (Node *) $3;
} }
@ -9630,6 +9630,20 @@ publication_for_tables:
} }
; ;
publication_table_list:
publication_table
{ $$ = list_make1($1); }
| publication_table_list ',' publication_table
{ $$ = lappend($1, $3); }
;
publication_table: relation_expr
{
PublicationTable *n = makeNode(PublicationTable);
n->relation = $1;
$$ = (Node *) n;
}
;
/***************************************************************************** /*****************************************************************************
* *
@ -9651,7 +9665,7 @@ AlterPublicationStmt:
n->options = $5; n->options = $5;
$$ = (Node *)n; $$ = (Node *)n;
} }
| ALTER PUBLICATION name ADD_P TABLE relation_expr_list | ALTER PUBLICATION name ADD_P TABLE publication_table_list
{ {
AlterPublicationStmt *n = makeNode(AlterPublicationStmt); AlterPublicationStmt *n = makeNode(AlterPublicationStmt);
n->pubname = $3; n->pubname = $3;
@ -9659,7 +9673,7 @@ AlterPublicationStmt:
n->tableAction = DEFELEM_ADD; n->tableAction = DEFELEM_ADD;
$$ = (Node *)n; $$ = (Node *)n;
} }
| ALTER PUBLICATION name SET TABLE relation_expr_list | ALTER PUBLICATION name SET TABLE publication_table_list
{ {
AlterPublicationStmt *n = makeNode(AlterPublicationStmt); AlterPublicationStmt *n = makeNode(AlterPublicationStmt);
n->pubname = $3; n->pubname = $3;
@ -9667,7 +9681,7 @@ AlterPublicationStmt:
n->tableAction = DEFELEM_SET; n->tableAction = DEFELEM_SET;
$$ = (Node *)n; $$ = (Node *)n;
} }
| ALTER PUBLICATION name DROP TABLE relation_expr_list | ALTER PUBLICATION name DROP TABLE publication_table_list
{ {
AlterPublicationStmt *n = makeNode(AlterPublicationStmt); AlterPublicationStmt *n = makeNode(AlterPublicationStmt);
n->pubname = $3; n->pubname = $3;

View File

@ -83,6 +83,11 @@ typedef struct Publication
PublicationActions pubactions; PublicationActions pubactions;
} Publication; } Publication;
typedef struct PublicationRelInfo
{
Relation relation;
} PublicationRelInfo;
extern Publication *GetPublication(Oid pubid); extern Publication *GetPublication(Oid pubid);
extern Publication *GetPublicationByName(const char *pubname, bool missing_ok); extern Publication *GetPublicationByName(const char *pubname, bool missing_ok);
extern List *GetRelationPublications(Oid relid); extern List *GetRelationPublications(Oid relid);
@ -108,7 +113,7 @@ extern List *GetAllTablesPublications(void);
extern List *GetAllTablesPublicationRelations(bool pubviaroot); extern List *GetAllTablesPublicationRelations(bool pubviaroot);
extern bool is_publishable_relation(Relation rel); extern bool is_publishable_relation(Relation rel);
extern ObjectAddress publication_add_relation(Oid pubid, Relation targetrel, extern ObjectAddress publication_add_relation(Oid pubid, PublicationRelInfo *targetrel,
bool if_not_exists); bool if_not_exists);
extern Oid get_publication_oid(const char *pubname, bool missing_ok); extern Oid get_publication_oid(const char *pubname, bool missing_ok);

View File

@ -490,6 +490,7 @@ typedef enum NodeTag
T_PartitionRangeDatum, T_PartitionRangeDatum,
T_PartitionCmd, T_PartitionCmd,
T_VacuumRelation, T_VacuumRelation,
T_PublicationTable,
/* /*
* TAGS FOR REPLICATION GRAMMAR PARSE NODES (replnodes.h) * TAGS FOR REPLICATION GRAMMAR PARSE NODES (replnodes.h)

View File

@ -3624,6 +3624,11 @@ typedef struct AlterTSConfigurationStmt
bool missing_ok; /* for DROP - skip error if missing? */ bool missing_ok; /* for DROP - skip error if missing? */
} AlterTSConfigurationStmt; } AlterTSConfigurationStmt;
typedef struct PublicationTable
{
NodeTag type;
RangeVar *relation; /* relation to be published */
} PublicationTable;
typedef struct CreatePublicationStmt typedef struct CreatePublicationStmt
{ {

View File

@ -2047,6 +2047,7 @@ PublicationActions
PublicationInfo PublicationInfo
PublicationPartOpt PublicationPartOpt
PublicationRelInfo PublicationRelInfo
PublicationTable
PullFilter PullFilter
PullFilterOps PullFilterOps
PushFilter PushFilter