PostgreSQL Source Code  git master
publicationcmds.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * publicationcmds.c
4  * publication manipulation
5  *
6  * Portions Copyright (c) 1996-2021, 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 "access/genam.h"
18 #include "access/htup_details.h"
19 #include "access/table.h"
20 #include "access/xact.h"
21 #include "catalog/catalog.h"
22 #include "catalog/indexing.h"
23 #include "catalog/namespace.h"
24 #include "catalog/objectaccess.h"
25 #include "catalog/objectaddress.h"
26 #include "catalog/partition.h"
27 #include "catalog/pg_inherits.h"
28 #include "catalog/pg_publication.h"
30 #include "catalog/pg_type.h"
31 #include "commands/dbcommands.h"
32 #include "commands/defrem.h"
33 #include "commands/event_trigger.h"
35 #include "funcapi.h"
36 #include "miscadmin.h"
37 #include "utils/acl.h"
38 #include "utils/array.h"
39 #include "utils/builtins.h"
40 #include "utils/catcache.h"
41 #include "utils/fmgroids.h"
42 #include "utils/inval.h"
43 #include "utils/lsyscache.h"
44 #include "utils/rel.h"
45 #include "utils/syscache.h"
46 #include "utils/varlena.h"
47 
48 static List *OpenTableList(List *tables);
49 static void CloseTableList(List *rels);
50 static void PublicationAddTables(Oid pubid, List *rels, bool if_not_exists,
52 static void PublicationDropTables(Oid pubid, List *rels, bool missing_ok);
53 
54 static void
56  List *options,
57  bool *publish_given,
58  PublicationActions *pubactions,
59  bool *publish_via_partition_root_given,
60  bool *publish_via_partition_root)
61 {
62  ListCell *lc;
63 
64  *publish_given = false;
65  *publish_via_partition_root_given = false;
66 
67  /* defaults */
68  pubactions->pubinsert = true;
69  pubactions->pubupdate = true;
70  pubactions->pubdelete = true;
71  pubactions->pubtruncate = true;
72  *publish_via_partition_root = false;
73 
74  /* Parse options */
75  foreach(lc, options)
76  {
77  DefElem *defel = (DefElem *) lfirst(lc);
78 
79  if (strcmp(defel->defname, "publish") == 0)
80  {
81  char *publish;
82  List *publish_list;
83  ListCell *lc;
84 
85  if (*publish_given)
86  errorConflictingDefElem(defel, pstate);
87 
88  /*
89  * If publish option was given only the explicitly listed actions
90  * should be published.
91  */
92  pubactions->pubinsert = false;
93  pubactions->pubupdate = false;
94  pubactions->pubdelete = false;
95  pubactions->pubtruncate = false;
96 
97  *publish_given = true;
98  publish = defGetString(defel);
99 
100  if (!SplitIdentifierString(publish, ',', &publish_list))
101  ereport(ERROR,
102  (errcode(ERRCODE_SYNTAX_ERROR),
103  errmsg("invalid list syntax for \"publish\" option")));
104 
105  /* Process the option list. */
106  foreach(lc, publish_list)
107  {
108  char *publish_opt = (char *) lfirst(lc);
109 
110  if (strcmp(publish_opt, "insert") == 0)
111  pubactions->pubinsert = true;
112  else if (strcmp(publish_opt, "update") == 0)
113  pubactions->pubupdate = true;
114  else if (strcmp(publish_opt, "delete") == 0)
115  pubactions->pubdelete = true;
116  else if (strcmp(publish_opt, "truncate") == 0)
117  pubactions->pubtruncate = true;
118  else
119  ereport(ERROR,
120  (errcode(ERRCODE_SYNTAX_ERROR),
121  errmsg("unrecognized \"publish\" value: \"%s\"", publish_opt)));
122  }
123  }
124  else if (strcmp(defel->defname, "publish_via_partition_root") == 0)
125  {
126  if (*publish_via_partition_root_given)
127  errorConflictingDefElem(defel, pstate);
128  *publish_via_partition_root_given = true;
129  *publish_via_partition_root = defGetBoolean(defel);
130  }
131  else
132  ereport(ERROR,
133  (errcode(ERRCODE_SYNTAX_ERROR),
134  errmsg("unrecognized publication parameter: \"%s\"", defel->defname)));
135  }
136 }
137 
138 /*
139  * Create new publication.
140  */
143 {
144  Relation rel;
145  ObjectAddress myself;
146  Oid puboid;
147  bool nulls[Natts_pg_publication];
148  Datum values[Natts_pg_publication];
149  HeapTuple tup;
150  bool publish_given;
151  PublicationActions pubactions;
152  bool publish_via_partition_root_given;
153  bool publish_via_partition_root;
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 = table_open(PublicationRelationId, RowExclusiveLock);
169 
170  /* Check if name is used */
171  puboid = GetSysCacheOid1(PUBLICATIONNAME, Anum_pg_publication_oid,
172  CStringGetDatum(stmt->pubname));
173  if (OidIsValid(puboid))
174  {
175  ereport(ERROR,
177  errmsg("publication \"%s\" already exists",
178  stmt->pubname)));
179  }
180 
181  /* Form a tuple. */
182  memset(values, 0, sizeof(values));
183  memset(nulls, false, sizeof(nulls));
184 
185  values[Anum_pg_publication_pubname - 1] =
187  values[Anum_pg_publication_pubowner - 1] = ObjectIdGetDatum(GetUserId());
188 
190  stmt->options,
191  &publish_given, &pubactions,
192  &publish_via_partition_root_given,
193  &publish_via_partition_root);
194 
195  puboid = GetNewOidWithIndex(rel, PublicationObjectIndexId,
196  Anum_pg_publication_oid);
197  values[Anum_pg_publication_oid - 1] = ObjectIdGetDatum(puboid);
198  values[Anum_pg_publication_puballtables - 1] =
200  values[Anum_pg_publication_pubinsert - 1] =
201  BoolGetDatum(pubactions.pubinsert);
202  values[Anum_pg_publication_pubupdate - 1] =
203  BoolGetDatum(pubactions.pubupdate);
204  values[Anum_pg_publication_pubdelete - 1] =
205  BoolGetDatum(pubactions.pubdelete);
206  values[Anum_pg_publication_pubtruncate - 1] =
207  BoolGetDatum(pubactions.pubtruncate);
208  values[Anum_pg_publication_pubviaroot - 1] =
209  BoolGetDatum(publish_via_partition_root);
210 
211  tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
212 
213  /* Insert tuple into catalog. */
214  CatalogTupleInsert(rel, tup);
215  heap_freetuple(tup);
216 
217  recordDependencyOnOwner(PublicationRelationId, puboid, GetUserId());
218 
219  ObjectAddressSet(myself, PublicationRelationId, puboid);
220 
221  /* Make the changes visible. */
223 
224  if (stmt->tables)
225  {
226  List *rels;
227 
228  Assert(list_length(stmt->tables) > 0);
229 
230  rels = OpenTableList(stmt->tables);
231  PublicationAddTables(puboid, rels, true, NULL);
232  CloseTableList(rels);
233  }
234  else if (stmt->for_all_tables)
235  {
236  /* Invalidate relcache so that publication info is rebuilt. */
238  }
239 
241 
242  InvokeObjectPostCreateHook(PublicationRelationId, puboid, 0);
243 
245  {
247  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
248  errmsg("wal_level is insufficient to publish logical changes"),
249  errhint("Set wal_level to logical before creating subscriptions.")));
250  }
251 
252  return myself;
253 }
254 
255 /*
256  * Change options of a publication.
257  */
258 static void
260  Relation rel, HeapTuple tup)
261 {
262  bool nulls[Natts_pg_publication];
263  bool replaces[Natts_pg_publication];
264  Datum values[Natts_pg_publication];
265  bool publish_given;
266  PublicationActions pubactions;
267  bool publish_via_partition_root_given;
268  bool publish_via_partition_root;
269  ObjectAddress obj;
270  Form_pg_publication pubform;
271 
273  stmt->options,
274  &publish_given, &pubactions,
275  &publish_via_partition_root_given,
276  &publish_via_partition_root);
277 
278  /* Everything ok, form a new tuple. */
279  memset(values, 0, sizeof(values));
280  memset(nulls, false, sizeof(nulls));
281  memset(replaces, false, sizeof(replaces));
282 
283  if (publish_given)
284  {
285  values[Anum_pg_publication_pubinsert - 1] = BoolGetDatum(pubactions.pubinsert);
286  replaces[Anum_pg_publication_pubinsert - 1] = true;
287 
288  values[Anum_pg_publication_pubupdate - 1] = BoolGetDatum(pubactions.pubupdate);
289  replaces[Anum_pg_publication_pubupdate - 1] = true;
290 
291  values[Anum_pg_publication_pubdelete - 1] = BoolGetDatum(pubactions.pubdelete);
292  replaces[Anum_pg_publication_pubdelete - 1] = true;
293 
294  values[Anum_pg_publication_pubtruncate - 1] = BoolGetDatum(pubactions.pubtruncate);
295  replaces[Anum_pg_publication_pubtruncate - 1] = true;
296  }
297 
298  if (publish_via_partition_root_given)
299  {
300  values[Anum_pg_publication_pubviaroot - 1] = BoolGetDatum(publish_via_partition_root);
301  replaces[Anum_pg_publication_pubviaroot - 1] = true;
302  }
303 
304  tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls,
305  replaces);
306 
307  /* Update the catalog. */
308  CatalogTupleUpdate(rel, &tup->t_self, tup);
309 
311 
312  pubform = (Form_pg_publication) GETSTRUCT(tup);
313 
314  /* Invalidate the relcache. */
315  if (pubform->puballtables)
316  {
318  }
319  else
320  {
321  /*
322  * For any partitioned tables contained in the publication, we must
323  * invalidate all partitions contained in the respective partition
324  * trees, not just those explicitly mentioned in the publication.
325  */
326  List *relids = GetPublicationRelations(pubform->oid,
328 
330  }
331 
332  ObjectAddressSet(obj, PublicationRelationId, pubform->oid);
334  (Node *) stmt);
335 
336  InvokeObjectPostAlterHook(PublicationRelationId, pubform->oid, 0);
337 }
338 
339 /*
340  * Invalidate the relations.
341  */
342 void
344 {
345  /*
346  * We don't want to send too many individual messages, at some point it's
347  * cheaper to just reset whole relcache.
348  */
349  if (list_length(relids) < MAX_RELCACHE_INVAL_MSGS)
350  {
351  ListCell *lc;
352 
353  foreach(lc, relids)
355  }
356  else
358 }
359 
360 /*
361  * Add or remove table to/from publication.
362  */
363 static void
365  HeapTuple tup)
366 {
367  List *rels = NIL;
369  Oid pubid = pubform->oid;
370 
371  /* Check that user is allowed to manipulate the publication tables. */
372  if (pubform->puballtables)
373  ereport(ERROR,
374  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
375  errmsg("publication \"%s\" is defined as FOR ALL TABLES",
376  NameStr(pubform->pubname)),
377  errdetail("Tables cannot be added to or dropped from FOR ALL TABLES publications.")));
378 
379  Assert(list_length(stmt->tables) > 0);
380 
381  rels = OpenTableList(stmt->tables);
382 
383  if (stmt->tableAction == DEFELEM_ADD)
384  PublicationAddTables(pubid, rels, false, stmt);
385  else if (stmt->tableAction == DEFELEM_DROP)
386  PublicationDropTables(pubid, rels, false);
387  else /* DEFELEM_SET */
388  {
389  List *oldrelids = GetPublicationRelations(pubid,
391  List *delrels = NIL;
392  ListCell *oldlc;
393 
394  /* Calculate which relations to drop. */
395  foreach(oldlc, oldrelids)
396  {
397  Oid oldrelid = lfirst_oid(oldlc);
398  ListCell *newlc;
399  bool found = false;
400 
401  foreach(newlc, rels)
402  {
403  PublicationRelInfo *newpubrel;
404 
405  newpubrel = (PublicationRelInfo *) lfirst(newlc);
406  if (RelationGetRelid(newpubrel->relation) == oldrelid)
407  {
408  found = true;
409  break;
410  }
411  }
412  /* Not yet in the list, open it and add to the list */
413  if (!found)
414  {
415  Relation oldrel;
416  PublicationRelInfo *pubrel;
417 
418  /* Wrap relation into PublicationRelInfo */
419  oldrel = table_open(oldrelid, ShareUpdateExclusiveLock);
420 
421  pubrel = palloc(sizeof(PublicationRelInfo));
422  pubrel->relation = oldrel;
423 
424  delrels = lappend(delrels, pubrel);
425  }
426  }
427 
428  /* And drop them. */
429  PublicationDropTables(pubid, delrels, true);
430 
431  /*
432  * Don't bother calculating the difference for adding, we'll catch and
433  * skip existing ones when doing catalog update.
434  */
435  PublicationAddTables(pubid, rels, true, stmt);
436 
437  CloseTableList(delrels);
438  }
439 
440  CloseTableList(rels);
441 }
442 
443 /*
444  * Alter the existing publication.
445  *
446  * This is dispatcher function for AlterPublicationOptions and
447  * AlterPublicationTables.
448  */
449 void
451 {
452  Relation rel;
453  HeapTuple tup;
454  Form_pg_publication pubform;
455 
456  rel = table_open(PublicationRelationId, RowExclusiveLock);
457 
459  CStringGetDatum(stmt->pubname));
460 
461  if (!HeapTupleIsValid(tup))
462  ereport(ERROR,
463  (errcode(ERRCODE_UNDEFINED_OBJECT),
464  errmsg("publication \"%s\" does not exist",
465  stmt->pubname)));
466 
467  pubform = (Form_pg_publication) GETSTRUCT(tup);
468 
469  /* must be owner */
470  if (!pg_publication_ownercheck(pubform->oid, GetUserId()))
472  stmt->pubname);
473 
474  if (stmt->options)
475  AlterPublicationOptions(pstate, stmt, rel, tup);
476  else
477  AlterPublicationTables(stmt, rel, tup);
478 
479  /* Cleanup. */
480  heap_freetuple(tup);
482 }
483 
484 /*
485  * Remove relation from publication by mapping OID.
486  */
487 void
489 {
490  Relation rel;
491  HeapTuple tup;
493  List *relids = NIL;
494 
495  rel = table_open(PublicationRelRelationId, RowExclusiveLock);
496 
498 
499  if (!HeapTupleIsValid(tup))
500  elog(ERROR, "cache lookup failed for publication table %u",
501  proid);
502 
503  pubrel = (Form_pg_publication_rel) GETSTRUCT(tup);
504 
505  /*
506  * Invalidate relcache so that publication info is rebuilt.
507  *
508  * For the partitioned tables, we must invalidate all partitions contained
509  * in the respective partition hierarchies, not just the one explicitly
510  * mentioned in the publication. This is required because we implicitly
511  * publish the child tables when the parent table is published.
512  */
514  pubrel->prrelid);
515 
517 
518  CatalogTupleDelete(rel, &tup->t_self);
519 
520  ReleaseSysCache(tup);
521 
523 }
524 
525 /*
526  * Remove the publication by mapping OID.
527  */
528 void
530 {
531  Relation rel;
532  HeapTuple tup;
533  Form_pg_publication pubform;
534 
535  rel = table_open(PublicationRelationId, RowExclusiveLock);
536 
538  if (!HeapTupleIsValid(tup))
539  elog(ERROR, "cache lookup failed for publication %u", pubid);
540 
541  pubform = (Form_pg_publication)GETSTRUCT(tup);
542 
543  /* Invalidate relcache so that publication info is rebuilt. */
544  if (pubform->puballtables)
546 
547  CatalogTupleDelete(rel, &tup->t_self);
548 
549  ReleaseSysCache(tup);
550 
552 }
553 
554 /*
555  * Open relations specified by a PublicationTable list.
556  * In the returned list of PublicationRelInfo, tables are locked
557  * in ShareUpdateExclusiveLock mode in order to add them to a publication.
558  */
559 static List *
561 {
562  List *relids = NIL;
563  List *rels = NIL;
564  ListCell *lc;
565 
566  /*
567  * Open, share-lock, and check all the explicitly-specified relations
568  */
569  foreach(lc, tables)
570  {
572  bool recurse = t->relation->inh;
573  Relation rel;
574  Oid myrelid;
575  PublicationRelInfo *pub_rel;
576 
577  /* Allow query cancel in case this takes a long time */
579 
581  myrelid = RelationGetRelid(rel);
582 
583  /*
584  * Filter out duplicates if user specifies "foo, foo".
585  *
586  * Note that this algorithm is known to not be very efficient (O(N^2))
587  * but given that it only works on list of tables given to us by user
588  * it's deemed acceptable.
589  */
590  if (list_member_oid(relids, myrelid))
591  {
593  continue;
594  }
595 
596  pub_rel = palloc(sizeof(PublicationRelInfo));
597  pub_rel->relation = rel;
598  rels = lappend(rels, pub_rel);
599  relids = lappend_oid(relids, myrelid);
600 
601  /*
602  * Add children of this rel, if requested, so that they too are added
603  * to the publication. A partitioned table can't have any inheritance
604  * children other than its partitions, which need not be explicitly
605  * added to the publication.
606  */
607  if (recurse && rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
608  {
609  List *children;
610  ListCell *child;
611 
612  children = find_all_inheritors(myrelid, ShareUpdateExclusiveLock,
613  NULL);
614 
615  foreach(child, children)
616  {
617  Oid childrelid = lfirst_oid(child);
618 
619  /* Allow query cancel in case this takes a long time */
621 
622  /*
623  * Skip duplicates if user specified both parent and child
624  * tables.
625  */
626  if (list_member_oid(relids, childrelid))
627  continue;
628 
629  /* find_all_inheritors already got lock */
630  rel = table_open(childrelid, NoLock);
631  pub_rel = palloc(sizeof(PublicationRelInfo));
632  pub_rel->relation = rel;
633  rels = lappend(rels, pub_rel);
634  relids = lappend_oid(relids, childrelid);
635  }
636  }
637  }
638 
639  list_free(relids);
640 
641  return rels;
642 }
643 
644 /*
645  * Close all relations in the list.
646  */
647 static void
649 {
650  ListCell *lc;
651 
652  foreach(lc, rels)
653  {
654  PublicationRelInfo *pub_rel;
655 
656  pub_rel = (PublicationRelInfo *) lfirst(lc);
657  table_close(pub_rel->relation, NoLock);
658  }
659 }
660 
661 /*
662  * Add listed tables to the publication.
663  */
664 static void
665 PublicationAddTables(Oid pubid, List *rels, bool if_not_exists,
667 {
668  ListCell *lc;
669 
670  Assert(!stmt || !stmt->for_all_tables);
671 
672  foreach(lc, rels)
673  {
674  PublicationRelInfo *pub_rel = (PublicationRelInfo *) lfirst(lc);
675  Relation rel = pub_rel->relation;
676  ObjectAddress obj;
677 
678  /* Must be owner of the table or superuser. */
682 
683  obj = publication_add_relation(pubid, pub_rel, if_not_exists);
684  if (stmt)
685  {
687  (Node *) stmt);
688 
689  InvokeObjectPostCreateHook(PublicationRelRelationId,
690  obj.objectId, 0);
691  }
692  }
693 }
694 
695 /*
696  * Remove listed tables from the publication.
697  */
698 static void
699 PublicationDropTables(Oid pubid, List *rels, bool missing_ok)
700 {
701  ObjectAddress obj;
702  ListCell *lc;
703  Oid prid;
704 
705  foreach(lc, rels)
706  {
707  PublicationRelInfo *pubrel = (PublicationRelInfo *) lfirst(lc);
708  Relation rel = pubrel->relation;
709  Oid relid = RelationGetRelid(rel);
710 
711  prid = GetSysCacheOid2(PUBLICATIONRELMAP, Anum_pg_publication_rel_oid,
712  ObjectIdGetDatum(relid),
713  ObjectIdGetDatum(pubid));
714  if (!OidIsValid(prid))
715  {
716  if (missing_ok)
717  continue;
718 
719  ereport(ERROR,
720  (errcode(ERRCODE_UNDEFINED_OBJECT),
721  errmsg("relation \"%s\" is not part of the publication",
722  RelationGetRelationName(rel))));
723  }
724 
725  ObjectAddressSet(obj, PublicationRelRelationId, prid);
726  performDeletion(&obj, DROP_CASCADE, 0);
727  }
728 }
729 
730 /*
731  * Internal workhorse for changing a publication owner
732  */
733 static void
735 {
736  Form_pg_publication form;
737 
738  form = (Form_pg_publication) GETSTRUCT(tup);
739 
740  if (form->pubowner == newOwnerId)
741  return;
742 
743  if (!superuser())
744  {
745  AclResult aclresult;
746 
747  /* Must be owner */
748  if (!pg_publication_ownercheck(form->oid, GetUserId()))
750  NameStr(form->pubname));
751 
752  /* Must be able to become new owner */
753  check_is_member_of_role(GetUserId(), newOwnerId);
754 
755  /* New owner must have CREATE privilege on database */
756  aclresult = pg_database_aclcheck(MyDatabaseId, newOwnerId, ACL_CREATE);
757  if (aclresult != ACLCHECK_OK)
758  aclcheck_error(aclresult, OBJECT_DATABASE,
760 
761  if (form->puballtables && !superuser_arg(newOwnerId))
762  ereport(ERROR,
763  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
764  errmsg("permission denied to change owner of publication \"%s\"",
765  NameStr(form->pubname)),
766  errhint("The owner of a FOR ALL TABLES publication must be a superuser.")));
767  }
768 
769  form->pubowner = newOwnerId;
770  CatalogTupleUpdate(rel, &tup->t_self, tup);
771 
772  /* Update owner dependency reference */
773  changeDependencyOnOwner(PublicationRelationId,
774  form->oid,
775  newOwnerId);
776 
777  InvokeObjectPostAlterHook(PublicationRelationId,
778  form->oid, 0);
779 }
780 
781 /*
782  * Change publication owner -- by name
783  */
785 AlterPublicationOwner(const char *name, Oid newOwnerId)
786 {
787  Oid subid;
788  HeapTuple tup;
789  Relation rel;
790  ObjectAddress address;
791  Form_pg_publication pubform;
792 
793  rel = table_open(PublicationRelationId, RowExclusiveLock);
794 
796 
797  if (!HeapTupleIsValid(tup))
798  ereport(ERROR,
799  (errcode(ERRCODE_UNDEFINED_OBJECT),
800  errmsg("publication \"%s\" does not exist", name)));
801 
802  pubform = (Form_pg_publication) GETSTRUCT(tup);
803  subid = pubform->oid;
804 
805  AlterPublicationOwner_internal(rel, tup, newOwnerId);
806 
807  ObjectAddressSet(address, PublicationRelationId, subid);
808 
809  heap_freetuple(tup);
810 
812 
813  return address;
814 }
815 
816 /*
817  * Change publication owner -- by OID
818  */
819 void
821 {
822  HeapTuple tup;
823  Relation rel;
824 
825  rel = table_open(PublicationRelationId, RowExclusiveLock);
826 
828 
829  if (!HeapTupleIsValid(tup))
830  ereport(ERROR,
831  (errcode(ERRCODE_UNDEFINED_OBJECT),
832  errmsg("publication with OID %u does not exist", subid)));
833 
834  AlterPublicationOwner_internal(rel, tup, newOwnerId);
835 
836  heap_freetuple(tup);
837 
839 }
#define NIL
Definition: pg_list.h:65
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:381
static void PublicationAddTables(Oid pubid, List *rels, bool if_not_exists, AlterPublicationStmt *stmt)
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:48
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
int errhint(const char *fmt,...)
Definition: elog.c:1156
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
ObjectAddress publication_add_relation(Oid pubid, PublicationRelInfo *targetrel, bool if_not_exists)
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
List * GetPublicationRelations(Oid pubid, PublicationPartOpt pub_partopt)
#define RelationGetDescr(relation)
Definition: rel.h:503
Oid GetUserId(void)
Definition: miscinit.c:495
ObjectAddress CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
static void PublicationDropTables(Oid pubid, List *rels, bool missing_ok)
#define GetSysCacheOid1(cacheId, oidcol, key1)
Definition: syscache.h:193
int wal_level
Definition: xlog.c:108
static void AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt, Relation rel, HeapTuple tup)
RangeVar * relation
Definition: parsenodes.h:3642
bool pg_publication_ownercheck(Oid pub_oid, Oid roleid)
Definition: aclchk.c:5356
Definition: nodes.h:536
int errcode(int sqlerrcode)
Definition: elog.c:698
bool superuser(void)
Definition: superuser.c:46
void RemovePublicationById(Oid pubid)
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
void RemovePublicationRelById(Oid proid)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:626
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:163
Form_pg_class rd_rel
Definition: rel.h:109
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:372
#define OidIsValid(objectId)
Definition: c.h:710
static void CloseTableList(List *rels)
void changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
Definition: pg_shdepend.c:311
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3308
bool defGetBoolean(DefElem *def)
Definition: define.c:106
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define ACL_CREATE
Definition: parsenodes.h:92
char * defGetString(DefElem *def)
Definition: define.c:49
ItemPointerData t_self
Definition: htup.h:65
#define lfirst_node(type, lc)
Definition: pg_list.h:172
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2113
#define NoLock
Definition: lockdefs.h:34
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition: varlena.c:3746
#define RowExclusiveLock
Definition: lockdefs.h:38
struct statement * stmt
int errdetail(const char *fmt,...)
Definition: elog.c:1042
#define CStringGetDatum(X)
Definition: postgres.h:622
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:313
void CacheInvalidateRelcacheByRelid(Oid relid)
Definition: inval.c:1401
List * GetPubPartitionOptionRelations(List *result, PublicationPartOpt pub_partopt, Oid relid)
#define RelationGetRelationName(relation)
Definition: rel.h:511
static void parse_publication_options(ParseState *pstate, List *options, bool *publish_given, PublicationActions *pubactions, bool *publish_via_partition_root_given, bool *publish_via_partition_root)
void check_is_member_of_role(Oid member, Oid role)
Definition: acl.c:4893
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
static void AlterPublicationOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
bool superuser_arg(Oid roleid)
Definition: superuser.c:56
bool inh
Definition: primnodes.h:69
List * lappend(List *list, void *datum)
Definition: list.c:336
static void AlterPublicationTables(AlterPublicationStmt *stmt, Relation rel, HeapTuple tup)
#define WARNING
Definition: elog.h:40
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void CacheInvalidateRelcacheAll(void)
Definition: inval.c:1366
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:411
void CommandCounterIncrement(void)
Definition: xact.c:1022
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
Oid MyDatabaseId
Definition: globals.c:88
ObjectAddress AlterPublicationOwner(const char *name, Oid newOwnerId)
#define BoolGetDatum(X)
Definition: postgres.h:446
Relation table_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: table.c:102
DefElemAction tableAction
Definition: parsenodes.h:3665
#define ereport(elevel,...)
Definition: elog.h:157
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:350
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:689
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
AclResult pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4706
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4818
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition: syscache.h:195
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
static int list_length(const List *l)
Definition: pg_list.h:149
const char * name
Definition: encode.c:561
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:175
List * find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
Definition: pg_inherits.c:256
const ObjectAddress InvalidObjectAddress
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
void list_free(List *list)
Definition: list.c:1391
#define elog(elevel,...)
Definition: elog.h:232
FormData_pg_publication_rel * Form_pg_publication_rel
ObjectType get_relkind_objtype(char relkind)
#define NameStr(name)
Definition: c.h:681
void InvalidatePublicationRels(List *relids)
char * defname
Definition: parsenodes.h:758
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:120
void AlterPublicationOwner_oid(Oid subid, Oid newOwnerId)
void EventTriggerCollectSimpleCommand(ObjectAddress address, ObjectAddress secondaryObject, Node *parsetree)
FormData_pg_publication * Form_pg_publication
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
Definition: pg_list.h:50
void AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt)
#define RelationGetRelid(relation)
Definition: rel.h:477
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
#define MAX_RELCACHE_INVAL_MSGS
static List * OpenTableList(List *tables)
#define lfirst_oid(lc)
Definition: pg_list.h:171