PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
publicationcmds.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * publicationcmds.c
4  * publication manipulation
5  *
6  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * IDENTIFICATION
10  * publicationcmds.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 
15 #include "postgres.h"
16 
17 #include "funcapi.h"
18 #include "miscadmin.h"
19 
20 #include "access/genam.h"
21 #include "access/hash.h"
22 #include "access/heapam.h"
23 #include "access/htup_details.h"
24 #include "access/xact.h"
25 
26 #include "catalog/catalog.h"
27 #include "catalog/indexing.h"
28 #include "catalog/namespace.h"
29 #include "catalog/objectaccess.h"
30 #include "catalog/objectaddress.h"
31 #include "catalog/pg_inherits_fn.h"
32 #include "catalog/pg_type.h"
33 #include "catalog/pg_publication.h"
35 
36 #include "commands/dbcommands.h"
37 #include "commands/defrem.h"
38 #include "commands/event_trigger.h"
40 
41 #include "utils/array.h"
42 #include "utils/builtins.h"
43 #include "utils/catcache.h"
44 #include "utils/fmgroids.h"
45 #include "utils/inval.h"
46 #include "utils/lsyscache.h"
47 #include "utils/rel.h"
48 #include "utils/syscache.h"
49 
50 /* Same as MAXNUMMESSAGES in sinvaladt.c */
51 #define MAX_RELCACHE_INVAL_MSGS 4096
52 
53 static List *OpenTableList(List *tables);
54 static void CloseTableList(List *rels);
55 static void PublicationAddTables(Oid pubid, List *rels, bool if_not_exists,
57 static void PublicationDropTables(Oid pubid, List *rels, bool missing_ok);
58 
59 static void
61  bool *publish_insert_given,
62  bool *publish_insert,
63  bool *publish_update_given,
64  bool *publish_update,
65  bool *publish_delete_given,
66  bool *publish_delete)
67 {
68  ListCell *lc;
69 
70  *publish_insert_given = false;
71  *publish_update_given = false;
72  *publish_delete_given = false;
73 
74  /* Defaults are true */
75  *publish_insert = true;
76  *publish_update = true;
77  *publish_delete = true;
78 
79  /* Parse options */
80  foreach (lc, options)
81  {
82  DefElem *defel = (DefElem *) lfirst(lc);
83 
84  if (strcmp(defel->defname, "publish insert") == 0)
85  {
86  if (*publish_insert_given)
87  ereport(ERROR,
88  (errcode(ERRCODE_SYNTAX_ERROR),
89  errmsg("conflicting or redundant options")));
90 
91  *publish_insert_given = true;
92  *publish_insert = defGetBoolean(defel);
93  }
94  else if (strcmp(defel->defname, "nopublish insert") == 0)
95  {
96  if (*publish_insert_given)
97  ereport(ERROR,
98  (errcode(ERRCODE_SYNTAX_ERROR),
99  errmsg("conflicting or redundant options")));
100 
101  *publish_insert_given = true;
102  *publish_insert = !defGetBoolean(defel);
103  }
104  else if (strcmp(defel->defname, "publish update") == 0)
105  {
106  if (*publish_update_given)
107  ereport(ERROR,
108  (errcode(ERRCODE_SYNTAX_ERROR),
109  errmsg("conflicting or redundant options")));
110 
111  *publish_update_given = true;
112  *publish_update = defGetBoolean(defel);
113  }
114  else if (strcmp(defel->defname, "nopublish update") == 0)
115  {
116  if (*publish_update_given)
117  ereport(ERROR,
118  (errcode(ERRCODE_SYNTAX_ERROR),
119  errmsg("conflicting or redundant options")));
120 
121  *publish_update_given = true;
122  *publish_update = !defGetBoolean(defel);
123  }
124  else if (strcmp(defel->defname, "publish delete") == 0)
125  {
126  if (*publish_delete_given)
127  ereport(ERROR,
128  (errcode(ERRCODE_SYNTAX_ERROR),
129  errmsg("conflicting or redundant options")));
130 
131  *publish_delete_given = true;
132  *publish_delete = defGetBoolean(defel);
133  }
134  else if (strcmp(defel->defname, "nopublish delete") == 0)
135  {
136  if (*publish_delete_given)
137  ereport(ERROR,
138  (errcode(ERRCODE_SYNTAX_ERROR),
139  errmsg("conflicting or redundant options")));
140 
141  *publish_delete_given = true;
142  *publish_delete = !defGetBoolean(defel);
143  }
144  else
145  elog(ERROR, "unrecognized option: %s", defel->defname);
146  }
147 }
148 
149 /*
150  * Create new publication.
151  */
154 {
155  Relation rel;
156  ObjectAddress myself;
157  Oid puboid;
158  bool nulls[Natts_pg_publication];
160  HeapTuple tup;
161  bool publish_insert_given;
162  bool publish_update_given;
163  bool publish_delete_given;
164  bool publish_insert;
165  bool publish_update;
166  bool publish_delete;
167  AclResult aclresult;
168 
169  /* must have CREATE privilege on database */
171  if (aclresult != ACLCHECK_OK)
174 
175  /* FOR ALL TABLES requires superuser */
176  if (stmt->for_all_tables && !superuser())
177  ereport(ERROR,
178  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
179  (errmsg("must be superuser to create FOR ALL TABLES publication"))));
180 
182 
183  /* Check if name is used */
185  if (OidIsValid(puboid))
186  {
187  ereport(ERROR,
189  errmsg("publication \"%s\" already exists",
190  stmt->pubname)));
191  }
192 
193  /* Form a tuple. */
194  memset(values, 0, sizeof(values));
195  memset(nulls, false, sizeof(nulls));
196 
197  values[Anum_pg_publication_pubname - 1] =
200 
202  &publish_insert_given, &publish_insert,
203  &publish_update_given, &publish_update,
204  &publish_delete_given, &publish_delete);
205 
208  values[Anum_pg_publication_pubinsert - 1] =
209  BoolGetDatum(publish_insert);
210  values[Anum_pg_publication_pubupdate - 1] =
211  BoolGetDatum(publish_update);
212  values[Anum_pg_publication_pubdelete - 1] =
213  BoolGetDatum(publish_delete);
214 
215  tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
216 
217  /* Insert tuple into catalog. */
218  puboid = CatalogTupleInsert(rel, tup);
219  heap_freetuple(tup);
220 
222 
223  ObjectAddressSet(myself, PublicationRelationId, puboid);
224 
225  /* Make the changes visible. */
227 
228  if (stmt->tables)
229  {
230  List *rels;
231 
232  Assert(list_length(stmt->tables) > 0);
233 
234  rels = OpenTableList(stmt->tables);
235  PublicationAddTables(puboid, rels, true, NULL);
236  CloseTableList(rels);
237  }
238 
240 
242 
243  return myself;
244 }
245 
246 /*
247  * Change options of a publication.
248  */
249 static void
251  HeapTuple tup)
252 {
253  bool nulls[Natts_pg_publication];
254  bool replaces[Natts_pg_publication];
256  bool publish_insert_given;
257  bool publish_update_given;
258  bool publish_delete_given;
259  bool publish_insert;
260  bool publish_update;
261  bool publish_delete;
262  ObjectAddress obj;
263 
265  &publish_insert_given, &publish_insert,
266  &publish_update_given, &publish_update,
267  &publish_delete_given, &publish_delete);
268 
269  /* Everything ok, form a new tuple. */
270  memset(values, 0, sizeof(values));
271  memset(nulls, false, sizeof(nulls));
272  memset(replaces, false, sizeof(replaces));
273 
274  if (publish_insert_given)
275  {
276  values[Anum_pg_publication_pubinsert - 1] =
277  BoolGetDatum(publish_insert);
278  replaces[Anum_pg_publication_pubinsert - 1] = true;
279  }
280  if (publish_update_given)
281  {
282  values[Anum_pg_publication_pubupdate - 1] =
283  BoolGetDatum(publish_update);
284  replaces[Anum_pg_publication_pubupdate - 1] = true;
285  }
286  if (publish_delete_given)
287  {
288  values[Anum_pg_publication_pubdelete - 1] =
289  BoolGetDatum(publish_delete);
290  replaces[Anum_pg_publication_pubdelete - 1] = true;
291  }
292 
293  tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls,
294  replaces);
295 
296  /* Update the catalog. */
297  CatalogTupleUpdate(rel, &tup->t_self, tup);
298 
300 
301  /* Invalidate the relcache. */
302  if (((Form_pg_publication) GETSTRUCT(tup))->puballtables)
303  {
305  }
306  else
307  {
309 
310  /*
311  * We don't want to send too many individual messages, at some point
312  * it's cheaper to just reset whole relcache.
313  */
314  if (list_length(relids) < MAX_RELCACHE_INVAL_MSGS)
315  {
316  ListCell *lc;
317 
318  foreach (lc, relids)
319  {
320  Oid relid = lfirst_oid(lc);
321 
323  }
324  }
325  else
327  }
328 
331  (Node *) stmt);
332 
334 }
335 
336 /*
337  * Add or remove table to/from publication.
338  */
339 static void
341  HeapTuple tup)
342 {
343  Oid pubid = HeapTupleGetOid(tup);
344  List *rels = NIL;
346 
347  /* Check that user is allowed to manipulate the publication tables. */
348  if (pubform->puballtables)
349  ereport(ERROR,
350  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
351  errmsg("publication \"%s\" is defined as FOR ALL TABLES",
352  NameStr(pubform->pubname)),
353  errdetail("Tables cannot be added to or dropped from FOR ALL TABLES publications.")));
354 
355  Assert(list_length(stmt->tables) > 0);
356 
357  rels = OpenTableList(stmt->tables);
358 
359  if (stmt->tableAction == DEFELEM_ADD)
360  PublicationAddTables(pubid, rels, false, stmt);
361  else if (stmt->tableAction == DEFELEM_DROP)
362  PublicationDropTables(pubid, rels, false);
363  else /* DEFELEM_SET */
364  {
365  List *oldrelids = GetPublicationRelations(pubid);
366  List *delrels = NIL;
367  ListCell *oldlc;
368 
369  /* Calculate which relations to drop. */
370  foreach(oldlc, oldrelids)
371  {
372  Oid oldrelid = lfirst_oid(oldlc);
373  ListCell *newlc;
374  bool found = false;
375 
376  foreach(newlc, rels)
377  {
378  Relation newrel = (Relation) lfirst(newlc);
379 
380  if (RelationGetRelid(newrel) == oldrelid)
381  {
382  found = true;
383  break;
384  }
385  }
386 
387  if (!found)
388  {
389  Relation oldrel = heap_open(oldrelid,
391  delrels = lappend(delrels, oldrel);
392  }
393  }
394 
395  /* And drop them. */
396  PublicationDropTables(pubid, delrels, true);
397 
398  /*
399  * Don't bother calculating the difference for adding, we'll catch
400  * and skip existing ones when doing catalog update.
401  */
402  PublicationAddTables(pubid, rels, true, stmt);
403 
404  CloseTableList(delrels);
405  }
406 
407  CloseTableList(rels);
408 }
409 
410 /*
411  * Alter the existing publication.
412  *
413  * This is dispatcher function for AlterPublicationOptions and
414  * AlterPublicationTables.
415  */
416 void
418 {
419  Relation rel;
420  HeapTuple tup;
421 
423 
425  CStringGetDatum(stmt->pubname));
426 
427  if (!HeapTupleIsValid(tup))
428  ereport(ERROR,
429  (errcode(ERRCODE_UNDEFINED_OBJECT),
430  errmsg("publication \"%s\" does not exist",
431  stmt->pubname)));
432 
433  /* must be owner */
436  stmt->pubname);
437 
438  if (stmt->options)
439  AlterPublicationOptions(stmt, rel, tup);
440  else
441  AlterPublicationTables(stmt, rel, tup);
442 
443  /* Cleanup. */
444  heap_freetuple(tup);
446 }
447 
448 /*
449  * Drop publication by OID
450  */
451 void
453 {
454  Relation rel;
455  HeapTuple tup;
456 
458 
460 
461  if (!HeapTupleIsValid(tup))
462  elog(ERROR, "cache lookup failed for publication %u", pubid);
463 
464  CatalogTupleDelete(rel, &tup->t_self);
465 
466  ReleaseSysCache(tup);
467 
469 }
470 
471 /*
472  * Remove relation from publication by mapping OID.
473  */
474 void
476 {
477  Relation rel;
478  HeapTuple tup;
480 
482 
484 
485  if (!HeapTupleIsValid(tup))
486  elog(ERROR, "cache lookup failed for publication table %u",
487  proid);
488 
489  pubrel = (Form_pg_publication_rel) GETSTRUCT(tup);
490 
491  /* Invalidate relcache so that publication info is rebuilt. */
492  CacheInvalidateRelcacheByRelid(pubrel->prrelid);
493 
494  CatalogTupleDelete(rel, &tup->t_self);
495 
496  ReleaseSysCache(tup);
497 
499 }
500 
501 /*
502  * Open relations based om provided by RangeVar list.
503  * The returned tables are locked in ShareUpdateExclusiveLock mode.
504  */
505 static List *
507 {
508  List *relids = NIL;
509  List *rels = NIL;
510  ListCell *lc;
511 
512  /*
513  * Open, share-lock, and check all the explicitly-specified relations
514  */
515  foreach(lc, tables)
516  {
517  RangeVar *rv = lfirst(lc);
518  Relation rel;
519  bool recurse = rv->inh;
520  Oid myrelid;
521 
523 
525  myrelid = RelationGetRelid(rel);
526  /*
527  * filter out duplicates when user specifies "foo, foo"
528  * Note that this algorithm is know to not be very effective (O(N^2))
529  * but given that it only works on list of tables given to us by user
530  * it's deemed acceptable.
531  */
532  if (list_member_oid(relids, myrelid))
533  {
535  continue;
536  }
537  rels = lappend(rels, rel);
538  relids = lappend_oid(relids, myrelid);
539 
540  if (recurse)
541  {
542  ListCell *child;
543  List *children;
544 
545  children = find_all_inheritors(myrelid, ShareUpdateExclusiveLock,
546  NULL);
547 
548  foreach(child, children)
549  {
550  Oid childrelid = lfirst_oid(child);
551 
552  if (list_member_oid(relids, childrelid))
553  continue;
554 
555  /*
556  * Skip duplicates if user specified both parent and child
557  * tables.
558  */
559  if (list_member_oid(relids, childrelid))
560  {
562  continue;
563  }
564 
565  /* find_all_inheritors already got lock */
566  rel = heap_open(childrelid, NoLock);
567  rels = lappend(rels, rel);
568  relids = lappend_oid(relids, childrelid);
569  }
570  }
571  }
572 
573  list_free(relids);
574 
575  return rels;
576 }
577 
578 /*
579  * Close all relations in the list.
580  */
581 static void
583 {
584  ListCell *lc;
585 
586  foreach(lc, rels)
587  {
588  Relation rel = (Relation) lfirst(lc);
589 
590  heap_close(rel, NoLock);
591  }
592 }
593 
594 /*
595  * Add listed tables to the publication.
596  */
597 static void
598 PublicationAddTables(Oid pubid, List *rels, bool if_not_exists,
600 {
601  ListCell *lc;
602 
603  Assert(!stmt || !stmt->for_all_tables);
604 
605  foreach(lc, rels)
606  {
607  Relation rel = (Relation) lfirst(lc);
608  ObjectAddress obj;
609 
610  /* Must be owner of the table or superuser. */
614 
615  obj = publication_add_relation(pubid, rel, if_not_exists);
616  if (stmt)
617  {
619  (Node *) stmt);
620 
622  obj.objectId, 0);
623  }
624  }
625 }
626 
627 /*
628  * Remove listed tables from the publication.
629  */
630 static void
631 PublicationDropTables(Oid pubid, List *rels, bool missing_ok)
632 {
633  ObjectAddress obj;
634  ListCell *lc;
635  Oid prid;
636 
637  foreach(lc, rels)
638  {
639  Relation rel = (Relation) lfirst(lc);
640  Oid relid = RelationGetRelid(rel);
641 
643  ObjectIdGetDatum(pubid));
644  if (!OidIsValid(prid))
645  {
646  if (missing_ok)
647  continue;
648 
649  ereport(ERROR,
650  (errcode(ERRCODE_UNDEFINED_OBJECT),
651  errmsg("relation \"%s\" is not part of the publication",
652  RelationGetRelationName(rel))));
653  }
654 
656  performDeletion(&obj, DROP_CASCADE, 0);
657  }
658 }
659 
660 /*
661  * Internal workhorse for changing a publication owner
662  */
663  static void
665 {
666  Form_pg_publication form;
667 
668  form = (Form_pg_publication) GETSTRUCT(tup);
669 
670  if (form->pubowner == newOwnerId)
671  return;
672 
675  NameStr(form->pubname));
676 
677  /* New owner must be a superuser */
678  if (!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 publication must be a superuser.")));
684 
685  form->pubowner = newOwnerId;
686  CatalogTupleUpdate(rel, &tup->t_self, tup);
687 
688  /* Update owner dependency reference */
690  HeapTupleGetOid(tup),
691  newOwnerId);
692 
694  HeapTupleGetOid(tup), 0);
695 }
696 
697 /*
698  * Change publication owner -- by name
699  */
701 AlterPublicationOwner(const char *name, Oid newOwnerId)
702 {
703  Oid subid;
704  HeapTuple tup;
705  Relation rel;
706  ObjectAddress address;
707 
709 
711 
712  if (!HeapTupleIsValid(tup))
713  ereport(ERROR,
714  (errcode(ERRCODE_UNDEFINED_OBJECT),
715  errmsg("publication \"%s\" does not exist", name)));
716 
717  subid = HeapTupleGetOid(tup);
718 
719  AlterPublicationOwner_internal(rel, tup, newOwnerId);
720 
721  ObjectAddressSet(address, PublicationRelationId, subid);
722 
723  heap_freetuple(tup);
724 
726 
727  return address;
728 }
729 
730 /*
731  * Change publication owner -- by OID
732  */
733 void
735 {
736  HeapTuple tup;
737  Relation rel;
738 
740 
742 
743  if (!HeapTupleIsValid(tup))
744  ereport(ERROR,
745  (errcode(ERRCODE_UNDEFINED_OBJECT),
746  errmsg("publication with OID %u does not exist", subid)));
747 
748  AlterPublicationOwner_internal(rel, tup, newOwnerId);
749 
750  heap_freetuple(tup);
751 
753 }
#define NIL
Definition: pg_list.h:69
#define Natts_pg_publication
static void AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel, HeapTuple tup)
static void PublicationAddTables(Oid pubid, List *rels, bool if_not_exists, AlterPublicationStmt *stmt)
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:46
int errhint(const char *fmt,...)
Definition: elog.c:987
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
#define RelationGetDescr(relation)
Definition: rel.h:425
ObjectAddress CreatePublication(CreatePublicationStmt *stmt)
Oid GetUserId(void)
Definition: miscinit.c:283
static void PublicationDropTables(Oid pubid, List *rels, bool missing_ok)
bool pg_publication_ownercheck(Oid pub_oid, Oid roleid)
Definition: aclchk.c:5059
Definition: nodes.h:508
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
#define PublicationRelationId
void RemovePublicationById(Oid pubid)
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
void RemovePublicationRelById(Oid proid)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
#define heap_close(r, l)
Definition: heapam.h:97
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:555
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:158
static void parse_publication_options(List *options, bool *publish_insert_given, bool *publish_insert, bool *publish_update_given, bool *publish_update, bool *publish_delete_given, bool *publish_delete)
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
#define OidIsValid(objectId)
Definition: c.h:533
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
#define Anum_pg_publication_pubowner
#define GetSysCacheOid2(cacheId, key1, key2)
Definition: syscache.h:178
#define PublicationRelRelationId
#define GetSysCacheOid1(cacheId, key1)
Definition: syscache.h:176
static void CloseTableList(List *rels)
void changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
Definition: pg_shdepend.c:303
#define MAX_RELCACHE_INVAL_MSGS
bool defGetBoolean(DefElem *def)
Definition: define.c:111
struct RelationData * Relation
Definition: relcache.h:21
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:75
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
ItemPointerData t_self
Definition: htup.h:65
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2049
#define Anum_pg_publication_pubupdate
#define NoLock
Definition: lockdefs.h:34
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3378
#define RowExclusiveLock
Definition: lockdefs.h:38
struct statement * stmt
Definition: extern.h:74
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define CStringGetDatum(X)
Definition: postgres.h:586
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:301
void CacheInvalidateRelcacheByRelid(Oid relid)
Definition: inval.c:1282
#define RelationGetRelationName(relation)
Definition: rel.h:433
#define Anum_pg_publication_pubdelete
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
static void AlterPublicationOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
bool superuser_arg(Oid roleid)
Definition: superuser.c:57
bool inh
Definition: primnodes.h:68
List * lappend(List *list, void *datum)
Definition: list.c:128
static void AlterPublicationTables(AlterPublicationStmt *stmt, Relation rel, HeapTuple tup)
void CacheInvalidateRelcacheAll(void)
Definition: inval.c:1247
AclResult
Definition: acl.h:170
uintptr_t Datum
Definition: postgres.h:374
void CommandCounterIncrement(void)
Definition: xact.c:921
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
#define Anum_pg_publication_pubinsert
Oid MyDatabaseId
Definition: globals.c:76
ObjectAddress AlterPublicationOwner(const char *name, Oid newOwnerId)
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#define BoolGetDatum(X)
Definition: postgres.h:410
Relation heap_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: heapam.c:1315
DefElemAction tableAction
Definition: parsenodes.h:3276
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:505
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
AclResult pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4409
#define NULL
Definition: c.h:226
#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:4521
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
const char * name
Definition: encode.c:521
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
static Datum values[MAXATTR]
Definition: bootstrap.c:162
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:158
List * find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
Definition: pg_inherits.c:159
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define Anum_pg_publication_puballtables
void list_free(List *list)
Definition: list.c:1133
FormData_pg_publication_rel * Form_pg_publication_rel
#define NameStr(name)
Definition: c.h:494
char * defname
Definition: parsenodes.h:675
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97
ObjectAddress publication_add_relation(Oid pubid, Relation targetrel, bool if_not_exists)
void AlterPublicationOwner_oid(Oid subid, Oid newOwnerId)
#define elog
Definition: elog.h:219
void EventTriggerCollectSimpleCommand(ObjectAddress address, ObjectAddress secondaryObject, Node *parsetree)
#define Anum_pg_publication_pubname
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
FormData_pg_publication * Form_pg_publication
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:793
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:34
Definition: pg_list.h:45
#define RelationGetRelid(relation)
Definition: rel.h:413
static List * OpenTableList(List *tables)
#define lfirst_oid(lc)
Definition: pg_list.h:108
void AlterPublication(AlterPublicationStmt *stmt)