PostgreSQL Source Code  git master
publicationcmds.c File Reference
#include "postgres.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "access/genam.h"
#include "access/hash.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "access/xact.h"
#include "catalog/catalog.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/objectaccess.h"
#include "catalog/objectaddress.h"
#include "catalog/pg_inherits_fn.h"
#include "catalog/pg_type.h"
#include "catalog/pg_publication.h"
#include "catalog/pg_publication_rel.h"
#include "commands/dbcommands.h"
#include "commands/defrem.h"
#include "commands/event_trigger.h"
#include "commands/publicationcmds.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/catcache.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/syscache.h"
#include "utils/varlena.h"
Include dependency graph for publicationcmds.c:

Go to the source code of this file.

Macros

#define MAX_RELCACHE_INVAL_MSGS   4096
 

Functions

static ListOpenTableList (List *tables)
 
static void CloseTableList (List *rels)
 
static void PublicationAddTables (Oid pubid, List *rels, bool if_not_exists, AlterPublicationStmt *stmt)
 
static void PublicationDropTables (Oid pubid, List *rels, bool missing_ok)
 
static void parse_publication_options (List *options, bool *publish_given, bool *publish_insert, bool *publish_update, bool *publish_delete)
 
ObjectAddress CreatePublication (CreatePublicationStmt *stmt)
 
static void AlterPublicationOptions (AlterPublicationStmt *stmt, Relation rel, HeapTuple tup)
 
static void AlterPublicationTables (AlterPublicationStmt *stmt, Relation rel, HeapTuple tup)
 
void AlterPublication (AlterPublicationStmt *stmt)
 
void RemovePublicationById (Oid pubid)
 
void RemovePublicationRelById (Oid proid)
 
static void AlterPublicationOwner_internal (Relation rel, HeapTuple tup, Oid newOwnerId)
 
ObjectAddress AlterPublicationOwner (const char *name, Oid newOwnerId)
 
void AlterPublicationOwner_oid (Oid subid, Oid newOwnerId)
 

Macro Definition Documentation

◆ MAX_RELCACHE_INVAL_MSGS

#define MAX_RELCACHE_INVAL_MSGS   4096

Definition at line 52 of file publicationcmds.c.

Referenced by AlterPublicationOptions().

Function Documentation

◆ AlterPublication()

void AlterPublication ( AlterPublicationStmt stmt)

Definition at line 388 of file publicationcmds.c.

References ACL_KIND_PUBLICATION, aclcheck_error(), ACLCHECK_NOT_OWNER, AlterPublicationOptions(), AlterPublicationTables(), CStringGetDatum, ereport, errcode(), errmsg(), ERROR, GetUserId(), heap_close, heap_freetuple(), heap_open(), HeapTupleGetOid, HeapTupleIsValid, AlterPublicationStmt::options, pg_publication_ownercheck(), PUBLICATIONNAME, PublicationRelationId, AlterPublicationStmt::pubname, RowExclusiveLock, and SearchSysCacheCopy1.

Referenced by ProcessUtilitySlow().

389 {
390  Relation rel;
391  HeapTuple tup;
392 
394 
396  CStringGetDatum(stmt->pubname));
397 
398  if (!HeapTupleIsValid(tup))
399  ereport(ERROR,
400  (errcode(ERRCODE_UNDEFINED_OBJECT),
401  errmsg("publication \"%s\" does not exist",
402  stmt->pubname)));
403 
404  /* must be owner */
407  stmt->pubname);
408 
409  if (stmt->options)
410  AlterPublicationOptions(stmt, rel, tup);
411  else
412  AlterPublicationTables(stmt, rel, tup);
413 
414  /* Cleanup. */
415  heap_freetuple(tup);
417 }
static void AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel, HeapTuple tup)
Oid GetUserId(void)
Definition: miscinit.c:284
bool pg_publication_ownercheck(Oid pub_oid, Oid roleid)
Definition: aclchk.c:5084
int errcode(int sqlerrcode)
Definition: elog.c:575
#define PublicationRelationId
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
#define ERROR
Definition: elog.h:43
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3399
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:584
#define ereport(elevel, rest)
Definition: elog.h:122
static void AlterPublicationTables(AlterPublicationStmt *stmt, Relation rel, HeapTuple tup)
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700

◆ AlterPublicationOptions()

static void AlterPublicationOptions ( AlterPublicationStmt stmt,
Relation  rel,
HeapTuple  tup 
)
static

Definition at line 230 of file publicationcmds.c.

References Anum_pg_publication_pubdelete, Anum_pg_publication_pubinsert, Anum_pg_publication_pubupdate, BoolGetDatum, CacheInvalidateRelcacheAll(), CacheInvalidateRelcacheByRelid(), CatalogTupleUpdate(), CommandCounterIncrement(), EventTriggerCollectSimpleCommand(), GetPublicationRelations(), GETSTRUCT, heap_modify_tuple(), HeapTupleGetOid, InvalidObjectAddress, InvokeObjectPostAlterHook, lfirst_oid, list_length(), MAX_RELCACHE_INVAL_MSGS, Natts_pg_publication, ObjectAddressSet, AlterPublicationStmt::options, parse_publication_options(), PublicationRelationId, RelationGetDescr, HeapTupleData::t_self, and values.

Referenced by AlterPublication().

232 {
233  bool nulls[Natts_pg_publication];
234  bool replaces[Natts_pg_publication];
236  bool publish_given;
237  bool publish_insert;
238  bool publish_update;
239  bool publish_delete;
240  ObjectAddress obj;
241 
243  &publish_given, &publish_insert,
244  &publish_update, &publish_delete);
245 
246  /* Everything ok, form a new tuple. */
247  memset(values, 0, sizeof(values));
248  memset(nulls, false, sizeof(nulls));
249  memset(replaces, false, sizeof(replaces));
250 
251  if (publish_given)
252  {
253  values[Anum_pg_publication_pubinsert - 1] = BoolGetDatum(publish_insert);
254  replaces[Anum_pg_publication_pubinsert - 1] = true;
255 
256  values[Anum_pg_publication_pubupdate - 1] = BoolGetDatum(publish_update);
257  replaces[Anum_pg_publication_pubupdate - 1] = true;
258 
259  values[Anum_pg_publication_pubdelete - 1] = BoolGetDatum(publish_delete);
260  replaces[Anum_pg_publication_pubdelete - 1] = true;
261  }
262 
263  tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls,
264  replaces);
265 
266  /* Update the catalog. */
267  CatalogTupleUpdate(rel, &tup->t_self, tup);
268 
270 
271  /* Invalidate the relcache. */
272  if (((Form_pg_publication) GETSTRUCT(tup))->puballtables)
273  {
275  }
276  else
277  {
279 
280  /*
281  * We don't want to send too many individual messages, at some point
282  * it's cheaper to just reset whole relcache.
283  */
284  if (list_length(relids) < MAX_RELCACHE_INVAL_MSGS)
285  {
286  ListCell *lc;
287 
288  foreach(lc, relids)
289  {
290  Oid relid = lfirst_oid(lc);
291 
293  }
294  }
295  else
297  }
298 
301  (Node *) stmt);
302 
304 }
#define Natts_pg_publication
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define RelationGetDescr(relation)
Definition: rel.h:428
Definition: nodes.h:510
#define PublicationRelationId
unsigned int Oid
Definition: postgres_ext.h:31
#define MAX_RELCACHE_INVAL_MSGS
ItemPointerData t_self
Definition: htup.h:65
#define Anum_pg_publication_pubupdate
void CacheInvalidateRelcacheByRelid(Oid relid)
Definition: inval.c:1292
#define Anum_pg_publication_pubdelete
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
void CacheInvalidateRelcacheAll(void)
Definition: inval.c:1257
uintptr_t Datum
Definition: postgres.h:372
void CommandCounterIncrement(void)
Definition: xact.c:915
#define Anum_pg_publication_pubinsert
#define BoolGetDatum(X)
Definition: postgres.h:408
List * GetPublicationRelations(Oid pubid)
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
static int list_length(const List *l)
Definition: pg_list.h:89
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
static Datum values[MAXATTR]
Definition: bootstrap.c:164
const ObjectAddress InvalidObjectAddress
void EventTriggerCollectSimpleCommand(ObjectAddress address, ObjectAddress secondaryObject, Node *parsetree)
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700
static void parse_publication_options(List *options, bool *publish_given, bool *publish_insert, bool *publish_update, bool *publish_delete)
FormData_pg_publication * Form_pg_publication
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:794
Definition: pg_list.h:45
#define lfirst_oid(lc)
Definition: pg_list.h:108

◆ AlterPublicationOwner()

ObjectAddress AlterPublicationOwner ( const char *  name,
Oid  newOwnerId 
)

Definition at line 688 of file publicationcmds.c.

References AlterPublicationOwner_internal(), CStringGetDatum, ereport, errcode(), errmsg(), ERROR, heap_close, heap_freetuple(), heap_open(), HeapTupleGetOid, HeapTupleIsValid, ObjectAddressSet, PUBLICATIONNAME, PublicationRelationId, RowExclusiveLock, and SearchSysCacheCopy1.

Referenced by ExecAlterOwnerStmt().

689 {
690  Oid subid;
691  HeapTuple tup;
692  Relation rel;
693  ObjectAddress address;
694 
696 
698 
699  if (!HeapTupleIsValid(tup))
700  ereport(ERROR,
701  (errcode(ERRCODE_UNDEFINED_OBJECT),
702  errmsg("publication \"%s\" does not exist", name)));
703 
704  subid = HeapTupleGetOid(tup);
705 
706  AlterPublicationOwner_internal(rel, tup, newOwnerId);
707 
708  ObjectAddressSet(address, PublicationRelationId, subid);
709 
710  heap_freetuple(tup);
711 
713 
714  return address;
715 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define PublicationRelationId
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:584
#define ereport(elevel, rest)
Definition: elog.h:122
static void AlterPublicationOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
const char * name
Definition: encode.c:521
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700

◆ AlterPublicationOwner_internal()

static void AlterPublicationOwner_internal ( Relation  rel,
HeapTuple  tup,
Oid  newOwnerId 
)
static

Definition at line 637 of file publicationcmds.c.

References ACL_CREATE, ACL_KIND_DATABASE, ACL_KIND_PUBLICATION, aclcheck_error(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, CatalogTupleUpdate(), changeDependencyOnOwner(), check_is_member_of_role(), ereport, errcode(), errhint(), errmsg(), ERROR, get_database_name(), GETSTRUCT, GetUserId(), HeapTupleGetOid, InvokeObjectPostAlterHook, MyDatabaseId, NameStr, pg_database_aclcheck(), pg_publication_ownercheck(), PublicationRelationId, superuser(), superuser_arg(), and HeapTupleData::t_self.

Referenced by AlterPublicationOwner(), and AlterPublicationOwner_oid().

638 {
639  Form_pg_publication form;
640 
641  form = (Form_pg_publication) GETSTRUCT(tup);
642 
643  if (form->pubowner == newOwnerId)
644  return;
645 
646  if (!superuser())
647  {
648  AclResult aclresult;
649 
650  /* Must be owner */
653  NameStr(form->pubname));
654 
655  /* Must be able to become new owner */
656  check_is_member_of_role(GetUserId(), newOwnerId);
657 
658  /* New owner must have CREATE privilege on database */
659  aclresult = pg_database_aclcheck(MyDatabaseId, newOwnerId, ACL_CREATE);
660  if (aclresult != ACLCHECK_OK)
663 
664  if (form->puballtables && !superuser_arg(newOwnerId))
665  ereport(ERROR,
666  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
667  errmsg("permission denied to change owner of publication \"%s\"",
668  NameStr(form->pubname)),
669  errhint("The owner of a FOR ALL TABLES publication must be a superuser.")));
670  }
671 
672  form->pubowner = newOwnerId;
673  CatalogTupleUpdate(rel, &tup->t_self, tup);
674 
675  /* Update owner dependency reference */
677  HeapTupleGetOid(tup),
678  newOwnerId);
679 
681  HeapTupleGetOid(tup), 0);
682 }
int errhint(const char *fmt,...)
Definition: elog.c:987
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
Oid GetUserId(void)
Definition: miscinit.c:284
bool pg_publication_ownercheck(Oid pub_oid, Oid roleid)
Definition: aclchk.c:5084
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
#define PublicationRelationId
void changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
Definition: pg_shdepend.c:304
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:82
ItemPointerData t_self
Definition: htup.h:65
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2056
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3399
void check_is_member_of_role(Oid member, Oid role)
Definition: acl.c:4876
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
bool superuser_arg(Oid roleid)
Definition: superuser.c:57
AclResult
Definition: acl.h:178
Oid MyDatabaseId
Definition: globals.c:77
AclResult pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4434
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NameStr(name)
Definition: c.h:547
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700
FormData_pg_publication * Form_pg_publication

◆ AlterPublicationOwner_oid()

void AlterPublicationOwner_oid ( Oid  subid,
Oid  newOwnerId 
)

Definition at line 721 of file publicationcmds.c.

References AlterPublicationOwner_internal(), ereport, errcode(), errmsg(), ERROR, heap_close, heap_freetuple(), heap_open(), HeapTupleIsValid, ObjectIdGetDatum, PUBLICATIONOID, PublicationRelationId, RowExclusiveLock, and SearchSysCacheCopy1.

Referenced by shdepReassignOwned().

722 {
723  HeapTuple tup;
724  Relation rel;
725 
727 
729 
730  if (!HeapTupleIsValid(tup))
731  ereport(ERROR,
732  (errcode(ERRCODE_UNDEFINED_OBJECT),
733  errmsg("publication with OID %u does not exist", subid)));
734 
735  AlterPublicationOwner_internal(rel, tup, newOwnerId);
736 
737  heap_freetuple(tup);
738 
740 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define PublicationRelationId
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:122
static void AlterPublicationOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ AlterPublicationTables()

static void AlterPublicationTables ( AlterPublicationStmt stmt,
Relation  rel,
HeapTuple  tup 
)
static

Definition at line 310 of file publicationcmds.c.

References Assert, CloseTableList(), DEFELEM_ADD, DEFELEM_DROP, ereport, errcode(), errdetail(), errmsg(), ERROR, GetPublicationRelations(), GETSTRUCT, heap_open(), HeapTupleGetOid, lappend(), lfirst, lfirst_oid, list_length(), NameStr, NIL, OpenTableList(), PublicationAddTables(), PublicationDropTables(), RelationGetRelid, ShareUpdateExclusiveLock, AlterPublicationStmt::tableAction, and AlterPublicationStmt::tables.

Referenced by AlterPublication().

312 {
313  Oid pubid = HeapTupleGetOid(tup);
314  List *rels = NIL;
316 
317  /* Check that user is allowed to manipulate the publication tables. */
318  if (pubform->puballtables)
319  ereport(ERROR,
320  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
321  errmsg("publication \"%s\" is defined as FOR ALL TABLES",
322  NameStr(pubform->pubname)),
323  errdetail("Tables cannot be added to or dropped from FOR ALL TABLES publications.")));
324 
325  Assert(list_length(stmt->tables) > 0);
326 
327  rels = OpenTableList(stmt->tables);
328 
329  if (stmt->tableAction == DEFELEM_ADD)
330  PublicationAddTables(pubid, rels, false, stmt);
331  else if (stmt->tableAction == DEFELEM_DROP)
332  PublicationDropTables(pubid, rels, false);
333  else /* DEFELEM_SET */
334  {
335  List *oldrelids = GetPublicationRelations(pubid);
336  List *delrels = NIL;
337  ListCell *oldlc;
338 
339  /* Calculate which relations to drop. */
340  foreach(oldlc, oldrelids)
341  {
342  Oid oldrelid = lfirst_oid(oldlc);
343  ListCell *newlc;
344  bool found = false;
345 
346  foreach(newlc, rels)
347  {
348  Relation newrel = (Relation) lfirst(newlc);
349 
350  if (RelationGetRelid(newrel) == oldrelid)
351  {
352  found = true;
353  break;
354  }
355  }
356 
357  if (!found)
358  {
359  Relation oldrel = heap_open(oldrelid,
361 
362  delrels = lappend(delrels, oldrel);
363  }
364  }
365 
366  /* And drop them. */
367  PublicationDropTables(pubid, delrels, true);
368 
369  /*
370  * Don't bother calculating the difference for adding, we'll catch and
371  * skip existing ones when doing catalog update.
372  */
373  PublicationAddTables(pubid, rels, true, stmt);
374 
375  CloseTableList(delrels);
376  }
377 
378  CloseTableList(rels);
379 }
#define NIL
Definition: pg_list.h:69
static void PublicationAddTables(Oid pubid, List *rels, bool if_not_exists, AlterPublicationStmt *stmt)
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
static void PublicationDropTables(Oid pubid, List *rels, bool missing_ok)
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
static void CloseTableList(List *rels)
struct RelationData * Relation
Definition: relcache.h:26
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
List * lappend(List *list, void *datum)
Definition: list.c:128
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
DefElemAction tableAction
Definition: parsenodes.h:3417
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
List * GetPublicationRelations(Oid pubid)
static int list_length(const List *l)
Definition: pg_list.h:89
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NameStr(name)
Definition: c.h:547
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700
FormData_pg_publication * Form_pg_publication
Definition: pg_list.h:45
#define RelationGetRelid(relation)
Definition: rel.h:416
static List * OpenTableList(List *tables)
#define lfirst_oid(lc)
Definition: pg_list.h:108

◆ CloseTableList()

static void CloseTableList ( List rels)
static

Definition at line 555 of file publicationcmds.c.

References heap_close, lfirst, and NoLock.

Referenced by AlterPublicationTables(), and CreatePublication().

556 {
557  ListCell *lc;
558 
559  foreach(lc, rels)
560  {
561  Relation rel = (Relation) lfirst(lc);
562 
563  heap_close(rel, NoLock);
564  }
565 }
#define heap_close(r, l)
Definition: heapam.h:97
struct RelationData * Relation
Definition: relcache.h:26
#define NoLock
Definition: lockdefs.h:34
#define lfirst(lc)
Definition: pg_list.h:106

◆ CreatePublication()

ObjectAddress CreatePublication ( CreatePublicationStmt stmt)

Definition at line 136 of file publicationcmds.c.

References ACL_CREATE, ACL_KIND_DATABASE, aclcheck_error(), ACLCHECK_OK, Anum_pg_publication_puballtables, Anum_pg_publication_pubdelete, Anum_pg_publication_pubinsert, Anum_pg_publication_pubname, Anum_pg_publication_pubowner, Anum_pg_publication_pubupdate, Assert, BoolGetDatum, CatalogTupleInsert(), CloseTableList(), CommandCounterIncrement(), CStringGetDatum, DirectFunctionCall1, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, CreatePublicationStmt::for_all_tables, get_database_name(), GetSysCacheOid1, GetUserId(), heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), InvokeObjectPostCreateHook, list_length(), MyDatabaseId, namein(), Natts_pg_publication, ObjectAddressSet, ObjectIdGetDatum, OidIsValid, OpenTableList(), CreatePublicationStmt::options, parse_publication_options(), pg_database_aclcheck(), PublicationAddTables(), PUBLICATIONNAME, PublicationRelationId, CreatePublicationStmt::pubname, recordDependencyOnOwner(), RelationGetDescr, RowExclusiveLock, superuser(), CreatePublicationStmt::tables, and values.

Referenced by ProcessUtilitySlow().

137 {
138  Relation rel;
139  ObjectAddress myself;
140  Oid puboid;
141  bool nulls[Natts_pg_publication];
143  HeapTuple tup;
144  bool publish_given;
145  bool publish_insert;
146  bool publish_update;
147  bool publish_delete;
148  AclResult aclresult;
149 
150  /* must have CREATE privilege on database */
152  if (aclresult != ACLCHECK_OK)
155 
156  /* FOR ALL TABLES requires superuser */
157  if (stmt->for_all_tables && !superuser())
158  ereport(ERROR,
159  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
160  (errmsg("must be superuser to create FOR ALL TABLES publication"))));
161 
163 
164  /* Check if name is used */
166  if (OidIsValid(puboid))
167  {
168  ereport(ERROR,
170  errmsg("publication \"%s\" already exists",
171  stmt->pubname)));
172  }
173 
174  /* Form a tuple. */
175  memset(values, 0, sizeof(values));
176  memset(nulls, false, sizeof(nulls));
177 
178  values[Anum_pg_publication_pubname - 1] =
181 
183  &publish_given, &publish_insert,
184  &publish_update, &publish_delete);
185 
188  values[Anum_pg_publication_pubinsert - 1] =
189  BoolGetDatum(publish_insert);
190  values[Anum_pg_publication_pubupdate - 1] =
191  BoolGetDatum(publish_update);
192  values[Anum_pg_publication_pubdelete - 1] =
193  BoolGetDatum(publish_delete);
194 
195  tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
196 
197  /* Insert tuple into catalog. */
198  puboid = CatalogTupleInsert(rel, tup);
199  heap_freetuple(tup);
200 
202 
203  ObjectAddressSet(myself, PublicationRelationId, puboid);
204 
205  /* Make the changes visible. */
207 
208  if (stmt->tables)
209  {
210  List *rels;
211 
212  Assert(list_length(stmt->tables) > 0);
213 
214  rels = OpenTableList(stmt->tables);
215  PublicationAddTables(puboid, rels, true, NULL);
216  CloseTableList(rels);
217  }
218 
220 
222 
223  return myself;
224 }
#define Natts_pg_publication
static void PublicationAddTables(Oid pubid, List *rels, bool if_not_exists, AlterPublicationStmt *stmt)
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:46
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
#define RelationGetDescr(relation)
Definition: rel.h:428
Oid GetUserId(void)
Definition: miscinit.c:284
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
#define PublicationRelationId
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
#define heap_close(r, l)
Definition: heapam.h:97
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:159
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:576
#define Anum_pg_publication_pubowner
#define GetSysCacheOid1(cacheId, key1)
Definition: syscache.h:191
static void CloseTableList(List *rels)
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:82
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2056
#define Anum_pg_publication_pubupdate
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3399
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:584
#define Anum_pg_publication_pubdelete
#define ereport(elevel, rest)
Definition: elog.h:122
AclResult
Definition: acl.h:178
uintptr_t Datum
Definition: postgres.h:372
void CommandCounterIncrement(void)
Definition: xact.c:915
#define Anum_pg_publication_pubinsert
Oid MyDatabaseId
Definition: globals.c:77
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define BoolGetDatum(X)
Definition: postgres.h:408
AclResult pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4434
#define Assert(condition)
Definition: c.h:670
static int list_length(const List *l)
Definition: pg_list.h:89
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
static Datum values[MAXATTR]
Definition: bootstrap.c:164
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define Anum_pg_publication_puballtables
#define Anum_pg_publication_pubname
static void parse_publication_options(List *options, bool *publish_given, bool *publish_insert, bool *publish_update, bool *publish_delete)
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30
Definition: pg_list.h:45
static List * OpenTableList(List *tables)

◆ OpenTableList()

static List * OpenTableList ( List tables)
static

Definition at line 477 of file publicationcmds.c.

References CHECK_FOR_INTERRUPTS, find_all_inheritors(), heap_close, heap_open(), heap_openrv(), RangeVar::inh, lappend(), lappend_oid(), lfirst, lfirst_oid, list_free(), list_member_oid(), NIL, NoLock, RelationGetRelid, and ShareUpdateExclusiveLock.

Referenced by AlterPublicationTables(), and CreatePublication().

478 {
479  List *relids = NIL;
480  List *rels = NIL;
481  ListCell *lc;
482 
483  /*
484  * Open, share-lock, and check all the explicitly-specified relations
485  */
486  foreach(lc, tables)
487  {
488  RangeVar *rv = lfirst(lc);
489  Relation rel;
490  bool recurse = rv->inh;
491  Oid myrelid;
492 
494 
496  myrelid = RelationGetRelid(rel);
497 
498  /*
499  * Filter out duplicates if user specifies "foo, foo".
500  *
501  * Note that this algorithm is known to not be very efficient (O(N^2))
502  * but given that it only works on list of tables given to us by user
503  * it's deemed acceptable.
504  */
505  if (list_member_oid(relids, myrelid))
506  {
508  continue;
509  }
510  rels = lappend(rels, rel);
511  relids = lappend_oid(relids, myrelid);
512 
513  if (recurse)
514  {
515  ListCell *child;
516  List *children;
517 
518  children = find_all_inheritors(myrelid, ShareUpdateExclusiveLock,
519  NULL);
520 
521  foreach(child, children)
522  {
523  Oid childrelid = lfirst_oid(child);
524 
525  if (list_member_oid(relids, childrelid))
526  continue;
527 
528  /*
529  * Skip duplicates if user specified both parent and child
530  * tables.
531  */
532  if (list_member_oid(relids, childrelid))
533  {
535  continue;
536  }
537 
538  /* find_all_inheritors already got lock */
539  rel = heap_open(childrelid, NoLock);
540  rels = lappend(rels, rel);
541  relids = lappend_oid(relids, childrelid);
542  }
543  }
544  }
545 
546  list_free(relids);
547 
548  return rels;
549 }
#define NIL
Definition: pg_list.h:69
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
#define NoLock
Definition: lockdefs.h:34
bool inh
Definition: primnodes.h:69
List * lappend(List *list, void *datum)
Definition: list.c:128
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
Relation heap_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: heapam.c:1318
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:505
#define lfirst(lc)
Definition: pg_list.h:106
List * find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
Definition: pg_inherits.c:167
void list_free(List *list)
Definition: list.c:1133
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
Definition: pg_list.h:45
#define RelationGetRelid(relation)
Definition: rel.h:416
#define lfirst_oid(lc)
Definition: pg_list.h:108

◆ parse_publication_options()

static void parse_publication_options ( List options,
bool publish_given,
bool publish_insert,
bool publish_update,
bool publish_delete 
)
static

Definition at line 61 of file publicationcmds.c.

References defGetString(), DefElem::defname, ereport, errcode(), errmsg(), ERROR, lfirst, and SplitIdentifierString().

Referenced by AlterPublicationOptions(), and CreatePublication().

66 {
67  ListCell *lc;
68 
69  *publish_given = false;
70 
71  /* Defaults are true */
72  *publish_insert = true;
73  *publish_update = true;
74  *publish_delete = true;
75 
76  /* Parse options */
77  foreach(lc, options)
78  {
79  DefElem *defel = (DefElem *) lfirst(lc);
80 
81  if (strcmp(defel->defname, "publish") == 0)
82  {
83  char *publish;
84  List *publish_list;
85  ListCell *lc;
86 
87  if (*publish_given)
88  ereport(ERROR,
89  (errcode(ERRCODE_SYNTAX_ERROR),
90  errmsg("conflicting or redundant options")));
91 
92  /*
93  * If publish option was given only the explicitly listed actions
94  * should be published.
95  */
96  *publish_insert = false;
97  *publish_update = false;
98  *publish_delete = false;
99 
100  *publish_given = true;
101  publish = defGetString(defel);
102 
103  if (!SplitIdentifierString(publish, ',', &publish_list))
104  ereport(ERROR,
105  (errcode(ERRCODE_SYNTAX_ERROR),
106  errmsg("invalid list syntax for \"publish\" option")));
107 
108  /* Process the option list. */
109  foreach(lc, publish_list)
110  {
111  char *publish_opt = (char *) lfirst(lc);
112 
113  if (strcmp(publish_opt, "insert") == 0)
114  *publish_insert = true;
115  else if (strcmp(publish_opt, "update") == 0)
116  *publish_update = true;
117  else if (strcmp(publish_opt, "delete") == 0)
118  *publish_delete = true;
119  else
120  ereport(ERROR,
121  (errcode(ERRCODE_SYNTAX_ERROR),
122  errmsg("unrecognized \"publish\" value: \"%s\"", publish_opt)));
123  }
124  }
125  else
126  ereport(ERROR,
127  (errcode(ERRCODE_SYNTAX_ERROR),
128  errmsg("unrecognized publication parameter: %s", defel->defname)));
129  }
130 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
char * defGetString(DefElem *def)
Definition: define.c:49
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition: varlena.c:3264
#define ereport(elevel, rest)
Definition: elog.h:122
#define lfirst(lc)
Definition: pg_list.h:106
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * defname
Definition: parsenodes.h:719
Definition: pg_list.h:45

◆ PublicationAddTables()

static void PublicationAddTables ( Oid  pubid,
List rels,
bool  if_not_exists,
AlterPublicationStmt stmt 
)
static

Definition at line 571 of file publicationcmds.c.

References ACL_KIND_CLASS, aclcheck_error(), ACLCHECK_NOT_OWNER, Assert, EventTriggerCollectSimpleCommand(), AlterPublicationStmt::for_all_tables, GetUserId(), InvalidObjectAddress, InvokeObjectPostCreateHook, lfirst, ObjectAddress::objectId, pg_class_ownercheck(), publication_add_relation(), PublicationRelRelationId, RelationGetRelationName, and RelationGetRelid.

Referenced by AlterPublicationTables(), and CreatePublication().

573 {
574  ListCell *lc;
575 
576  Assert(!stmt || !stmt->for_all_tables);
577 
578  foreach(lc, rels)
579  {
580  Relation rel = (Relation) lfirst(lc);
581  ObjectAddress obj;
582 
583  /* Must be owner of the table or superuser. */
587 
588  obj = publication_add_relation(pubid, rel, if_not_exists);
589  if (stmt)
590  {
592  (Node *) stmt);
593 
595  obj.objectId, 0);
596  }
597  }
598 }
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
Oid GetUserId(void)
Definition: miscinit.c:284
Definition: nodes.h:510
#define PublicationRelRelationId
struct RelationData * Relation
Definition: relcache.h:26
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3399
#define RelationGetRelationName(relation)
Definition: rel.h:436
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4546
const ObjectAddress InvalidObjectAddress
ObjectAddress publication_add_relation(Oid pubid, Relation targetrel, bool if_not_exists)
void EventTriggerCollectSimpleCommand(ObjectAddress address, ObjectAddress secondaryObject, Node *parsetree)
#define RelationGetRelid(relation)
Definition: rel.h:416

◆ PublicationDropTables()

static void PublicationDropTables ( Oid  pubid,
List rels,
bool  missing_ok 
)
static

Definition at line 604 of file publicationcmds.c.

References DROP_CASCADE, ereport, errcode(), errmsg(), ERROR, GetSysCacheOid2, lfirst, ObjectAddressSet, ObjectIdGetDatum, OidIsValid, performDeletion(), PUBLICATIONRELMAP, PublicationRelRelationId, RelationGetRelationName, and RelationGetRelid.

Referenced by AlterPublicationTables().

605 {
606  ObjectAddress obj;
607  ListCell *lc;
608  Oid prid;
609 
610  foreach(lc, rels)
611  {
612  Relation rel = (Relation) lfirst(lc);
613  Oid relid = RelationGetRelid(rel);
614 
616  ObjectIdGetDatum(pubid));
617  if (!OidIsValid(prid))
618  {
619  if (missing_ok)
620  continue;
621 
622  ereport(ERROR,
623  (errcode(ERRCODE_UNDEFINED_OBJECT),
624  errmsg("relation \"%s\" is not part of the publication",
625  RelationGetRelationName(rel))));
626  }
627 
629  performDeletion(&obj, DROP_CASCADE, 0);
630  }
631 }
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:576
#define GetSysCacheOid2(cacheId, key1, key2)
Definition: syscache.h:193
#define PublicationRelRelationId
struct RelationData * Relation
Definition: relcache.h:26
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:303
#define RelationGetRelationName(relation)
Definition: rel.h:436
#define ereport(elevel, rest)
Definition: elog.h:122
#define lfirst(lc)
Definition: pg_list.h:106
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define RelationGetRelid(relation)
Definition: rel.h:416

◆ RemovePublicationById()

void RemovePublicationById ( Oid  pubid)

Definition at line 423 of file publicationcmds.c.

References CatalogTupleDelete(), elog, ERROR, heap_close, heap_open(), HeapTupleIsValid, ObjectIdGetDatum, PUBLICATIONOID, PublicationRelationId, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), and HeapTupleData::t_self.

Referenced by doDeletion().

424 {
425  Relation rel;
426  HeapTuple tup;
427 
429 
431 
432  if (!HeapTupleIsValid(tup))
433  elog(ERROR, "cache lookup failed for publication %u", pubid);
434 
435  CatalogTupleDelete(rel, &tup->t_self);
436 
437  ReleaseSysCache(tup);
438 
440 }
#define PublicationRelationId
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#define heap_close(r, l)
Definition: heapam.h:97
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define elog
Definition: elog.h:219

◆ RemovePublicationRelById()

void RemovePublicationRelById ( Oid  proid)

Definition at line 446 of file publicationcmds.c.

References CacheInvalidateRelcacheByRelid(), CatalogTupleDelete(), elog, ERROR, GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, ObjectIdGetDatum, PUBLICATIONREL, PublicationRelRelationId, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), and HeapTupleData::t_self.

Referenced by doDeletion().

447 {
448  Relation rel;
449  HeapTuple tup;
451 
453 
455 
456  if (!HeapTupleIsValid(tup))
457  elog(ERROR, "cache lookup failed for publication table %u",
458  proid);
459 
460  pubrel = (Form_pg_publication_rel) GETSTRUCT(tup);
461 
462  /* Invalidate relcache so that publication info is rebuilt. */
463  CacheInvalidateRelcacheByRelid(pubrel->prrelid);
464 
465  CatalogTupleDelete(rel, &tup->t_self);
466 
467  ReleaseSysCache(tup);
468 
470 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#define heap_close(r, l)
Definition: heapam.h:97
#define PublicationRelRelationId
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
void CacheInvalidateRelcacheByRelid(Oid relid)
Definition: inval.c:1292
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
FormData_pg_publication_rel * Form_pg_publication_rel
#define elog
Definition: elog.h:219