mirror of
https://github.com/postgres/postgres.git
synced 2025-07-07 00:36:50 +03:00
Allow publishing partition changes via ancestors
To control whether partition changes are replicated using their own identity and schema or an ancestor's, add a new parameter that can be set per publication named 'publish_via_partition_root'. This allows replicating a partitioned table into a different partition structure on the subscriber. Author: Amit Langote <amitlangote09@gmail.com> Reviewed-by: Rafia Sabih <rafia.pghackers@gmail.com> Reviewed-by: Peter Eisentraut <peter.eisentraut@2ndquadrant.com> Reviewed-by: Petr Jelinek <petr@2ndquadrant.com> Discussion: https://www.postgresql.org/message-id/flat/CA+HiwqH=Y85vRK3mOdjEkqFK+E=ST=eQiHdpj43L=_eJMOOznQ@mail.gmail.com
This commit is contained in:
@ -23,6 +23,7 @@
|
||||
#include "catalog/namespace.h"
|
||||
#include "catalog/objectaccess.h"
|
||||
#include "catalog/objectaddress.h"
|
||||
#include "catalog/partition.h"
|
||||
#include "catalog/pg_inherits.h"
|
||||
#include "catalog/pg_publication.h"
|
||||
#include "catalog/pg_publication_rel.h"
|
||||
@ -56,20 +57,21 @@ 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)
|
||||
PublicationActions *pubactions,
|
||||
bool *publish_via_partition_root_given,
|
||||
bool *publish_via_partition_root)
|
||||
{
|
||||
ListCell *lc;
|
||||
|
||||
*publish_given = false;
|
||||
*publish_via_partition_root_given = false;
|
||||
|
||||
/* Defaults are true */
|
||||
*publish_insert = true;
|
||||
*publish_update = true;
|
||||
*publish_delete = true;
|
||||
*publish_truncate = true;
|
||||
/* defaults */
|
||||
pubactions->pubinsert = true;
|
||||
pubactions->pubupdate = true;
|
||||
pubactions->pubdelete = true;
|
||||
pubactions->pubtruncate = true;
|
||||
*publish_via_partition_root = false;
|
||||
|
||||
/* Parse options */
|
||||
foreach(lc, options)
|
||||
@ -91,10 +93,10 @@ parse_publication_options(List *options,
|
||||
* If publish option was given only the explicitly listed actions
|
||||
* should be published.
|
||||
*/
|
||||
*publish_insert = false;
|
||||
*publish_update = false;
|
||||
*publish_delete = false;
|
||||
*publish_truncate = false;
|
||||
pubactions->pubinsert = false;
|
||||
pubactions->pubupdate = false;
|
||||
pubactions->pubdelete = false;
|
||||
pubactions->pubtruncate = false;
|
||||
|
||||
*publish_given = true;
|
||||
publish = defGetString(defel);
|
||||
@ -110,19 +112,28 @@ parse_publication_options(List *options,
|
||||
char *publish_opt = (char *) lfirst(lc);
|
||||
|
||||
if (strcmp(publish_opt, "insert") == 0)
|
||||
*publish_insert = true;
|
||||
pubactions->pubinsert = true;
|
||||
else if (strcmp(publish_opt, "update") == 0)
|
||||
*publish_update = true;
|
||||
pubactions->pubupdate = true;
|
||||
else if (strcmp(publish_opt, "delete") == 0)
|
||||
*publish_delete = true;
|
||||
pubactions->pubdelete = true;
|
||||
else if (strcmp(publish_opt, "truncate") == 0)
|
||||
*publish_truncate = true;
|
||||
pubactions->pubtruncate = true;
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("unrecognized \"publish\" value: \"%s\"", publish_opt)));
|
||||
}
|
||||
}
|
||||
else if (strcmp(defel->defname, "publish_via_partition_root") == 0)
|
||||
{
|
||||
if (*publish_via_partition_root_given)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
*publish_via_partition_root_given = true;
|
||||
*publish_via_partition_root = defGetBoolean(defel);
|
||||
}
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
@ -143,10 +154,9 @@ CreatePublication(CreatePublicationStmt *stmt)
|
||||
Datum values[Natts_pg_publication];
|
||||
HeapTuple tup;
|
||||
bool publish_given;
|
||||
bool publish_insert;
|
||||
bool publish_update;
|
||||
bool publish_delete;
|
||||
bool publish_truncate;
|
||||
PublicationActions pubactions;
|
||||
bool publish_via_partition_root_given;
|
||||
bool publish_via_partition_root;
|
||||
AclResult aclresult;
|
||||
|
||||
/* must have CREATE privilege on database */
|
||||
@ -183,9 +193,9 @@ CreatePublication(CreatePublicationStmt *stmt)
|
||||
values[Anum_pg_publication_pubowner - 1] = ObjectIdGetDatum(GetUserId());
|
||||
|
||||
parse_publication_options(stmt->options,
|
||||
&publish_given, &publish_insert,
|
||||
&publish_update, &publish_delete,
|
||||
&publish_truncate);
|
||||
&publish_given, &pubactions,
|
||||
&publish_via_partition_root_given,
|
||||
&publish_via_partition_root);
|
||||
|
||||
puboid = GetNewOidWithIndex(rel, PublicationObjectIndexId,
|
||||
Anum_pg_publication_oid);
|
||||
@ -193,13 +203,15 @@ CreatePublication(CreatePublicationStmt *stmt)
|
||||
values[Anum_pg_publication_puballtables - 1] =
|
||||
BoolGetDatum(stmt->for_all_tables);
|
||||
values[Anum_pg_publication_pubinsert - 1] =
|
||||
BoolGetDatum(publish_insert);
|
||||
BoolGetDatum(pubactions.pubinsert);
|
||||
values[Anum_pg_publication_pubupdate - 1] =
|
||||
BoolGetDatum(publish_update);
|
||||
BoolGetDatum(pubactions.pubupdate);
|
||||
values[Anum_pg_publication_pubdelete - 1] =
|
||||
BoolGetDatum(publish_delete);
|
||||
BoolGetDatum(pubactions.pubdelete);
|
||||
values[Anum_pg_publication_pubtruncate - 1] =
|
||||
BoolGetDatum(publish_truncate);
|
||||
BoolGetDatum(pubactions.pubtruncate);
|
||||
values[Anum_pg_publication_pubviaroot - 1] =
|
||||
BoolGetDatum(publish_via_partition_root);
|
||||
|
||||
tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
|
||||
|
||||
@ -251,17 +263,16 @@ AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
|
||||
bool replaces[Natts_pg_publication];
|
||||
Datum values[Natts_pg_publication];
|
||||
bool publish_given;
|
||||
bool publish_insert;
|
||||
bool publish_update;
|
||||
bool publish_delete;
|
||||
bool publish_truncate;
|
||||
PublicationActions pubactions;
|
||||
bool publish_via_partition_root_given;
|
||||
bool publish_via_partition_root;
|
||||
ObjectAddress obj;
|
||||
Form_pg_publication pubform;
|
||||
|
||||
parse_publication_options(stmt->options,
|
||||
&publish_given, &publish_insert,
|
||||
&publish_update, &publish_delete,
|
||||
&publish_truncate);
|
||||
&publish_given, &pubactions,
|
||||
&publish_via_partition_root_given,
|
||||
&publish_via_partition_root);
|
||||
|
||||
/* Everything ok, form a new tuple. */
|
||||
memset(values, 0, sizeof(values));
|
||||
@ -270,19 +281,25 @@ AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
|
||||
|
||||
if (publish_given)
|
||||
{
|
||||
values[Anum_pg_publication_pubinsert - 1] = BoolGetDatum(publish_insert);
|
||||
values[Anum_pg_publication_pubinsert - 1] = BoolGetDatum(pubactions.pubinsert);
|
||||
replaces[Anum_pg_publication_pubinsert - 1] = true;
|
||||
|
||||
values[Anum_pg_publication_pubupdate - 1] = BoolGetDatum(publish_update);
|
||||
values[Anum_pg_publication_pubupdate - 1] = BoolGetDatum(pubactions.pubupdate);
|
||||
replaces[Anum_pg_publication_pubupdate - 1] = true;
|
||||
|
||||
values[Anum_pg_publication_pubdelete - 1] = BoolGetDatum(publish_delete);
|
||||
values[Anum_pg_publication_pubdelete - 1] = BoolGetDatum(pubactions.pubdelete);
|
||||
replaces[Anum_pg_publication_pubdelete - 1] = true;
|
||||
|
||||
values[Anum_pg_publication_pubtruncate - 1] = BoolGetDatum(publish_truncate);
|
||||
values[Anum_pg_publication_pubtruncate - 1] = BoolGetDatum(pubactions.pubtruncate);
|
||||
replaces[Anum_pg_publication_pubtruncate - 1] = true;
|
||||
}
|
||||
|
||||
if (publish_via_partition_root_given)
|
||||
{
|
||||
values[Anum_pg_publication_pubviaroot - 1] = BoolGetDatum(publish_via_partition_root);
|
||||
replaces[Anum_pg_publication_pubviaroot - 1] = true;
|
||||
}
|
||||
|
||||
tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls,
|
||||
replaces);
|
||||
|
||||
|
Reference in New Issue
Block a user