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.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, bool *publish_truncate)
 
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 402 of file publicationcmds.c.

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

Referenced by ProcessUtilitySlow().

403 {
404  Relation rel;
405  HeapTuple tup;
406 
407  rel = heap_open(PublicationRelationId, RowExclusiveLock);
408 
410  CStringGetDatum(stmt->pubname));
411 
412  if (!HeapTupleIsValid(tup))
413  ereport(ERROR,
414  (errcode(ERRCODE_UNDEFINED_OBJECT),
415  errmsg("publication \"%s\" does not exist",
416  stmt->pubname)));
417 
418  /* must be owner */
421  stmt->pubname);
422 
423  if (stmt->options)
424  AlterPublicationOptions(stmt, rel, tup);
425  else
426  AlterPublicationTables(stmt, rel, tup);
427 
428  /* Cleanup. */
429  heap_freetuple(tup);
431 }
static void AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel, HeapTuple tup)
Oid GetUserId(void)
Definition: miscinit.c:379
bool pg_publication_ownercheck(Oid pub_oid, Oid roleid)
Definition: aclchk.c:5286
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3348
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:561
#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:1294
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:712

◆ AlterPublicationOptions()

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

Definition at line 239 of file publicationcmds.c.

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

Referenced by AlterPublication().

241 {
242  bool nulls[Natts_pg_publication];
243  bool replaces[Natts_pg_publication];
244  Datum values[Natts_pg_publication];
245  bool publish_given;
246  bool publish_insert;
247  bool publish_update;
248  bool publish_delete;
249  bool publish_truncate;
250  ObjectAddress obj;
251 
253  &publish_given, &publish_insert,
254  &publish_update, &publish_delete,
255  &publish_truncate);
256 
257  /* Everything ok, form a new tuple. */
258  memset(values, 0, sizeof(values));
259  memset(nulls, false, sizeof(nulls));
260  memset(replaces, false, sizeof(replaces));
261 
262  if (publish_given)
263  {
264  values[Anum_pg_publication_pubinsert - 1] = BoolGetDatum(publish_insert);
265  replaces[Anum_pg_publication_pubinsert - 1] = true;
266 
267  values[Anum_pg_publication_pubupdate - 1] = BoolGetDatum(publish_update);
268  replaces[Anum_pg_publication_pubupdate - 1] = true;
269 
270  values[Anum_pg_publication_pubdelete - 1] = BoolGetDatum(publish_delete);
271  replaces[Anum_pg_publication_pubdelete - 1] = true;
272 
273  values[Anum_pg_publication_pubtruncate - 1] = BoolGetDatum(publish_truncate);
274  replaces[Anum_pg_publication_pubtruncate - 1] = true;
275  }
276 
277  tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls,
278  replaces);
279 
280  /* Update the catalog. */
281  CatalogTupleUpdate(rel, &tup->t_self, tup);
282 
284 
285  /* Invalidate the relcache. */
286  if (((Form_pg_publication) GETSTRUCT(tup))->puballtables)
287  {
289  }
290  else
291  {
293 
294  /*
295  * We don't want to send too many individual messages, at some point
296  * it's cheaper to just reset whole relcache.
297  */
298  if (list_length(relids) < MAX_RELCACHE_INVAL_MSGS)
299  {
300  ListCell *lc;
301 
302  foreach(lc, relids)
303  {
304  Oid relid = lfirst_oid(lc);
305 
307  }
308  }
309  else
311  }
312 
313  ObjectAddressSet(obj, PublicationRelationId, HeapTupleGetOid(tup));
315  (Node *) stmt);
316 
317  InvokeObjectPostAlterHook(PublicationRelationId, HeapTupleGetOid(tup), 0);
318 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
#define RelationGetDescr(relation)
Definition: rel.h:433
Definition: nodes.h:517
unsigned int Oid
Definition: postgres_ext.h:31
#define MAX_RELCACHE_INVAL_MSGS
ItemPointerData t_self
Definition: htup.h:65
void CacheInvalidateRelcacheByRelid(Oid relid)
Definition: inval.c:1292
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
void CacheInvalidateRelcacheAll(void)
Definition: inval.c:1257
uintptr_t Datum
Definition: postgres.h:365
void CommandCounterIncrement(void)
Definition: xact.c:914
#define BoolGetDatum(X)
Definition: postgres.h:385
List * GetPublicationRelations(Oid pubid)
static void parse_publication_options(List *options, bool *publish_given, bool *publish_insert, bool *publish_update, bool *publish_delete, bool *publish_truncate)
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:211
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:712
FormData_pg_publication * Form_pg_publication
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1173
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 702 of file publicationcmds.c.

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

Referenced by ExecAlterOwnerStmt().

703 {
704  Oid subid;
705  HeapTuple tup;
706  Relation rel;
707  ObjectAddress address;
708 
709  rel = heap_open(PublicationRelationId, RowExclusiveLock);
710 
712 
713  if (!HeapTupleIsValid(tup))
714  ereport(ERROR,
715  (errcode(ERRCODE_UNDEFINED_OBJECT),
716  errmsg("publication \"%s\" does not exist", name)));
717 
718  subid = HeapTupleGetOid(tup);
719 
720  AlterPublicationOwner_internal(rel, tup, newOwnerId);
721 
722  ObjectAddressSet(address, PublicationRelationId, subid);
723 
724  heap_freetuple(tup);
725 
727 
728  return address;
729 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
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:561
#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:1294
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
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:712

◆ AlterPublicationOwner_internal()

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

Definition at line 651 of file publicationcmds.c.

References ACL_CREATE, 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, OBJECT_DATABASE, OBJECT_PUBLICATION, pg_database_aclcheck(), pg_publication_ownercheck(), superuser(), superuser_arg(), and HeapTupleData::t_self.

Referenced by AlterPublicationOwner(), and AlterPublicationOwner_oid().

652 {
653  Form_pg_publication form;
654 
655  form = (Form_pg_publication) GETSTRUCT(tup);
656 
657  if (form->pubowner == newOwnerId)
658  return;
659 
660  if (!superuser())
661  {
662  AclResult aclresult;
663 
664  /* Must be owner */
667  NameStr(form->pubname));
668 
669  /* Must be able to become new owner */
670  check_is_member_of_role(GetUserId(), newOwnerId);
671 
672  /* New owner must have CREATE privilege on database */
673  aclresult = pg_database_aclcheck(MyDatabaseId, newOwnerId, ACL_CREATE);
674  if (aclresult != ACLCHECK_OK)
675  aclcheck_error(aclresult, OBJECT_DATABASE,
677 
678  if (form->puballtables && !superuser_arg(newOwnerId))
679  ereport(ERROR,
680  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
681  errmsg("permission denied to change owner of publication \"%s\"",
682  NameStr(form->pubname)),
683  errhint("The owner of a FOR ALL TABLES publication must be a superuser.")));
684  }
685 
686  form->pubowner = newOwnerId;
687  CatalogTupleUpdate(rel, &tup->t_self, tup);
688 
689  /* Update owner dependency reference */
690  changeDependencyOnOwner(PublicationRelationId,
691  HeapTupleGetOid(tup),
692  newOwnerId);
693 
694  InvokeObjectPostAlterHook(PublicationRelationId,
695  HeapTupleGetOid(tup), 0);
696 }
int errhint(const char *fmt,...)
Definition: elog.c:987
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
Oid GetUserId(void)
Definition: miscinit.c:379
bool pg_publication_ownercheck(Oid pub_oid, Oid roleid)
Definition: aclchk.c:5286
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
void changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
Definition: pg_shdepend.c:304
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3348
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:84
ItemPointerData t_self
Definition: htup.h:65
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2056
void check_is_member_of_role(Oid member, Oid role)
Definition: acl.c:4879
#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:86
AclResult pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4636
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:211
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NameStr(name)
Definition: c.h:576
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:712
FormData_pg_publication * Form_pg_publication

◆ AlterPublicationOwner_oid()

void AlterPublicationOwner_oid ( Oid  subid,
Oid  newOwnerId 
)

Definition at line 735 of file publicationcmds.c.

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

Referenced by shdepReassignOwned().

736 {
737  HeapTuple tup;
738  Relation rel;
739 
740  rel = heap_open(PublicationRelationId, RowExclusiveLock);
741 
743 
744  if (!HeapTupleIsValid(tup))
745  ereport(ERROR,
746  (errcode(ERRCODE_UNDEFINED_OBJECT),
747  errmsg("publication with OID %u does not exist", subid)));
748 
749  AlterPublicationOwner_internal(rel, tup, newOwnerId);
750 
751  heap_freetuple(tup);
752 
754 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#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:1294
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#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 324 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().

326 {
327  Oid pubid = HeapTupleGetOid(tup);
328  List *rels = NIL;
330 
331  /* Check that user is allowed to manipulate the publication tables. */
332  if (pubform->puballtables)
333  ereport(ERROR,
334  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
335  errmsg("publication \"%s\" is defined as FOR ALL TABLES",
336  NameStr(pubform->pubname)),
337  errdetail("Tables cannot be added to or dropped from FOR ALL TABLES publications.")));
338 
339  Assert(list_length(stmt->tables) > 0);
340 
341  rels = OpenTableList(stmt->tables);
342 
343  if (stmt->tableAction == DEFELEM_ADD)
344  PublicationAddTables(pubid, rels, false, stmt);
345  else if (stmt->tableAction == DEFELEM_DROP)
346  PublicationDropTables(pubid, rels, false);
347  else /* DEFELEM_SET */
348  {
349  List *oldrelids = GetPublicationRelations(pubid);
350  List *delrels = NIL;
351  ListCell *oldlc;
352 
353  /* Calculate which relations to drop. */
354  foreach(oldlc, oldrelids)
355  {
356  Oid oldrelid = lfirst_oid(oldlc);
357  ListCell *newlc;
358  bool found = false;
359 
360  foreach(newlc, rels)
361  {
362  Relation newrel = (Relation) lfirst(newlc);
363 
364  if (RelationGetRelid(newrel) == oldrelid)
365  {
366  found = true;
367  break;
368  }
369  }
370 
371  if (!found)
372  {
373  Relation oldrel = heap_open(oldrelid,
375 
376  delrels = lappend(delrels, oldrel);
377  }
378  }
379 
380  /* And drop them. */
381  PublicationDropTables(pubid, delrels, true);
382 
383  /*
384  * Don't bother calculating the difference for adding, we'll catch and
385  * skip existing ones when doing catalog update.
386  */
387  PublicationAddTables(pubid, rels, true, stmt);
388 
389  CloseTableList(delrels);
390  }
391 
392  CloseTableList(rels);
393 }
#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:673
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:1294
DefElemAction tableAction
Definition: parsenodes.h:3452
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
#define Assert(condition)
Definition: c.h:699
#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:576
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:712
FormData_pg_publication * Form_pg_publication
Definition: pg_list.h:45
#define RelationGetRelid(relation)
Definition: rel.h:407
static List * OpenTableList(List *tables)
#define lfirst_oid(lc)
Definition: pg_list.h:108

◆ CloseTableList()

static void CloseTableList ( List rels)
static

Definition at line 569 of file publicationcmds.c.

References heap_close, lfirst, and NoLock.

Referenced by AlterPublicationTables(), and CreatePublication().

570 {
571  ListCell *lc;
572 
573  foreach(lc, rels)
574  {
575  Relation rel = (Relation) lfirst(lc);
576 
577  heap_close(rel, NoLock);
578  }
579 }
#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 141 of file publicationcmds.c.

References ACL_CREATE, aclcheck_error(), ACLCHECK_OK, 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(), OBJECT_DATABASE, ObjectAddressSet, ObjectIdGetDatum, OidIsValid, OpenTableList(), CreatePublicationStmt::options, parse_publication_options(), pg_database_aclcheck(), PublicationAddTables(), PUBLICATIONNAME, CreatePublicationStmt::pubname, recordDependencyOnOwner(), RelationGetDescr, RowExclusiveLock, superuser(), CreatePublicationStmt::tables, and values.

Referenced by ProcessUtilitySlow().

142 {
143  Relation rel;
144  ObjectAddress myself;
145  Oid puboid;
146  bool nulls[Natts_pg_publication];
147  Datum values[Natts_pg_publication];
148  HeapTuple tup;
149  bool publish_given;
150  bool publish_insert;
151  bool publish_update;
152  bool publish_delete;
153  bool publish_truncate;
154  AclResult aclresult;
155 
156  /* must have CREATE privilege on database */
158  if (aclresult != ACLCHECK_OK)
159  aclcheck_error(aclresult, OBJECT_DATABASE,
161 
162  /* FOR ALL TABLES requires superuser */
163  if (stmt->for_all_tables && !superuser())
164  ereport(ERROR,
165  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
166  (errmsg("must be superuser to create FOR ALL TABLES publication"))));
167 
168  rel = heap_open(PublicationRelationId, RowExclusiveLock);
169 
170  /* Check if name is used */
172  if (OidIsValid(puboid))
173  {
174  ereport(ERROR,
176  errmsg("publication \"%s\" already exists",
177  stmt->pubname)));
178  }
179 
180  /* Form a tuple. */
181  memset(values, 0, sizeof(values));
182  memset(nulls, false, sizeof(nulls));
183 
184  values[Anum_pg_publication_pubname - 1] =
186  values[Anum_pg_publication_pubowner - 1] = ObjectIdGetDatum(GetUserId());
187 
189  &publish_given, &publish_insert,
190  &publish_update, &publish_delete,
191  &publish_truncate);
192 
193  values[Anum_pg_publication_puballtables - 1] =
195  values[Anum_pg_publication_pubinsert - 1] =
196  BoolGetDatum(publish_insert);
197  values[Anum_pg_publication_pubupdate - 1] =
198  BoolGetDatum(publish_update);
199  values[Anum_pg_publication_pubdelete - 1] =
200  BoolGetDatum(publish_delete);
201  values[Anum_pg_publication_pubtruncate - 1] =
202  BoolGetDatum(publish_truncate);
203 
204  tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
205 
206  /* Insert tuple into catalog. */
207  puboid = CatalogTupleInsert(rel, tup);
208  heap_freetuple(tup);
209 
210  recordDependencyOnOwner(PublicationRelationId, puboid, GetUserId());
211 
212  ObjectAddressSet(myself, PublicationRelationId, puboid);
213 
214  /* Make the changes visible. */
216 
217  if (stmt->tables)
218  {
219  List *rels;
220 
221  Assert(list_length(stmt->tables) > 0);
222 
223  rels = OpenTableList(stmt->tables);
224  PublicationAddTables(puboid, rels, true, NULL);
225  CloseTableList(rels);
226  }
227 
229 
230  InvokeObjectPostCreateHook(PublicationRelationId, puboid, 0);
231 
232  return myself;
233 }
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:433
Oid GetUserId(void)
Definition: miscinit.c:379
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1074
#define heap_close(r, l)
Definition: heapam.h:97
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:159
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
#define GetSysCacheOid1(cacheId, key1)
Definition: syscache.h:191
static void CloseTableList(List *rels)
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3348
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:84
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:163
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2056
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:561
#define ereport(elevel, rest)
Definition: elog.h:122
AclResult
Definition: acl.h:178
uintptr_t Datum
Definition: postgres.h:365
void CommandCounterIncrement(void)
Definition: xact.c:914
Oid MyDatabaseId
Definition: globals.c:86
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define BoolGetDatum(X)
Definition: postgres.h:385
AclResult pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4636
#define Assert(condition)
Definition: c.h:699
static void parse_publication_options(List *options, bool *publish_given, bool *publish_insert, bool *publish_update, bool *publish_delete, bool *publish_truncate)
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 ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
Definition: pg_list.h:45
static List * OpenTableList(List *tables)

◆ OpenTableList()

static List * OpenTableList ( List tables)
static

Definition at line 491 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().

492 {
493  List *relids = NIL;
494  List *rels = NIL;
495  ListCell *lc;
496 
497  /*
498  * Open, share-lock, and check all the explicitly-specified relations
499  */
500  foreach(lc, tables)
501  {
502  RangeVar *rv = lfirst(lc);
503  Relation rel;
504  bool recurse = rv->inh;
505  Oid myrelid;
506 
508 
510  myrelid = RelationGetRelid(rel);
511 
512  /*
513  * Filter out duplicates if user specifies "foo, foo".
514  *
515  * Note that this algorithm is known to not be very efficient (O(N^2))
516  * but given that it only works on list of tables given to us by user
517  * it's deemed acceptable.
518  */
519  if (list_member_oid(relids, myrelid))
520  {
522  continue;
523  }
524  rels = lappend(rels, rel);
525  relids = lappend_oid(relids, myrelid);
526 
527  if (recurse)
528  {
529  ListCell *child;
530  List *children;
531 
532  children = find_all_inheritors(myrelid, ShareUpdateExclusiveLock,
533  NULL);
534 
535  foreach(child, children)
536  {
537  Oid childrelid = lfirst_oid(child);
538 
539  if (list_member_oid(relids, childrelid))
540  continue;
541 
542  /*
543  * Skip duplicates if user specified both parent and child
544  * tables.
545  */
546  if (list_member_oid(relids, childrelid))
547  {
549  continue;
550  }
551 
552  /* find_all_inheritors already got lock */
553  rel = heap_open(childrelid, NoLock);
554  rels = lappend(rels, rel);
555  relids = lappend_oid(relids, childrelid);
556  }
557  }
558  }
559 
560  list_free(relids);
561 
562  return rels;
563 }
#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:70
List * lappend(List *list, void *datum)
Definition: list.c:128
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
Relation heap_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: heapam.c:1323
#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:166
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:407
#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,
bool publish_truncate 
)
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().

67 {
68  ListCell *lc;
69 
70  *publish_given = false;
71 
72  /* Defaults are true */
73  *publish_insert = true;
74  *publish_update = true;
75  *publish_delete = true;
76  *publish_truncate = true;
77 
78  /* Parse options */
79  foreach(lc, options)
80  {
81  DefElem *defel = (DefElem *) lfirst(lc);
82 
83  if (strcmp(defel->defname, "publish") == 0)
84  {
85  char *publish;
86  List *publish_list;
87  ListCell *lc;
88 
89  if (*publish_given)
90  ereport(ERROR,
91  (errcode(ERRCODE_SYNTAX_ERROR),
92  errmsg("conflicting or redundant options")));
93 
94  /*
95  * If publish option was given only the explicitly listed actions
96  * should be published.
97  */
98  *publish_insert = false;
99  *publish_update = false;
100  *publish_delete = false;
101  *publish_truncate = false;
102 
103  *publish_given = true;
104  publish = defGetString(defel);
105 
106  if (!SplitIdentifierString(publish, ',', &publish_list))
107  ereport(ERROR,
108  (errcode(ERRCODE_SYNTAX_ERROR),
109  errmsg("invalid list syntax for \"publish\" option")));
110 
111  /* Process the option list. */
112  foreach(lc, publish_list)
113  {
114  char *publish_opt = (char *) lfirst(lc);
115 
116  if (strcmp(publish_opt, "insert") == 0)
117  *publish_insert = true;
118  else if (strcmp(publish_opt, "update") == 0)
119  *publish_update = true;
120  else if (strcmp(publish_opt, "delete") == 0)
121  *publish_delete = true;
122  else if (strcmp(publish_opt, "truncate") == 0)
123  *publish_truncate = true;
124  else
125  ereport(ERROR,
126  (errcode(ERRCODE_SYNTAX_ERROR),
127  errmsg("unrecognized \"publish\" value: \"%s\"", publish_opt)));
128  }
129  }
130  else
131  ereport(ERROR,
132  (errcode(ERRCODE_SYNTAX_ERROR),
133  errmsg("unrecognized publication parameter: %s", defel->defname)));
134  }
135 }
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:3290
#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:730
Definition: pg_list.h:45

◆ PublicationAddTables()

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

Definition at line 585 of file publicationcmds.c.

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

Referenced by AlterPublicationTables(), and CreatePublication().

587 {
588  ListCell *lc;
589 
590  Assert(!stmt || !stmt->for_all_tables);
591 
592  foreach(lc, rels)
593  {
594  Relation rel = (Relation) lfirst(lc);
595  ObjectAddress obj;
596 
597  /* Must be owner of the table or superuser. */
601 
602  obj = publication_add_relation(pubid, rel, if_not_exists);
603  if (stmt)
604  {
606  (Node *) stmt);
607 
608  InvokeObjectPostCreateHook(PublicationRelRelationId,
609  obj.objectId, 0);
610  }
611  }
612 }
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
Oid GetUserId(void)
Definition: miscinit.c:379
Definition: nodes.h:517
Form_pg_class rd_rel
Definition: rel.h:84
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3348
struct RelationData * Relation
Definition: relcache.h:26
#define RelationGetRelationName(relation)
Definition: rel.h:441
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4748
const ObjectAddress InvalidObjectAddress
ObjectType get_relkind_objtype(char relkind)
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:407

◆ PublicationDropTables()

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

Definition at line 618 of file publicationcmds.c.

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

Referenced by AlterPublicationTables().

619 {
620  ObjectAddress obj;
621  ListCell *lc;
622  Oid prid;
623 
624  foreach(lc, rels)
625  {
626  Relation rel = (Relation) lfirst(lc);
627  Oid relid = RelationGetRelid(rel);
628 
630  ObjectIdGetDatum(pubid));
631  if (!OidIsValid(prid))
632  {
633  if (missing_ok)
634  continue;
635 
636  ereport(ERROR,
637  (errcode(ERRCODE_UNDEFINED_OBJECT),
638  errmsg("relation \"%s\" is not part of the publication",
639  RelationGetRelationName(rel))));
640  }
641 
642  ObjectAddressSet(obj, PublicationRelRelationId, prid);
643  performDeletion(&obj, DROP_CASCADE, 0);
644  }
645 }
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
#define GetSysCacheOid2(cacheId, key1, key2)
Definition: syscache.h:193
struct RelationData * Relation
Definition: relcache.h:26
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:300
#define RelationGetRelationName(relation)
Definition: rel.h:441
#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:407

◆ RemovePublicationById()

void RemovePublicationById ( Oid  pubid)

Definition at line 437 of file publicationcmds.c.

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

Referenced by doDeletion().

438 {
439  Relation rel;
440  HeapTuple tup;
441 
442  rel = heap_open(PublicationRelationId, RowExclusiveLock);
443 
445 
446  if (!HeapTupleIsValid(tup))
447  elog(ERROR, "cache lookup failed for publication %u", pubid);
448 
449  CatalogTupleDelete(rel, &tup->t_self);
450 
451  ReleaseSysCache(tup);
452 
454 }
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:256
#define heap_close(r, l)
Definition: heapam.h:97
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#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:1294
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog
Definition: elog.h:219

◆ RemovePublicationRelById()

void RemovePublicationRelById ( Oid  proid)

Definition at line 460 of file publicationcmds.c.

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

Referenced by doDeletion().

461 {
462  Relation rel;
463  HeapTuple tup;
465 
466  rel = heap_open(PublicationRelRelationId, RowExclusiveLock);
467 
469 
470  if (!HeapTupleIsValid(tup))
471  elog(ERROR, "cache lookup failed for publication table %u",
472  proid);
473 
474  pubrel = (Form_pg_publication_rel) GETSTRUCT(tup);
475 
476  /* Invalidate relcache so that publication info is rebuilt. */
477  CacheInvalidateRelcacheByRelid(pubrel->prrelid);
478 
479  CatalogTupleDelete(rel, &tup->t_self);
480 
481  ReleaseSysCache(tup);
482 
484 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:256
#define heap_close(r, l)
Definition: heapam.h:97
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#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:1294
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_publication_rel * Form_pg_publication_rel
#define elog
Definition: elog.h:219