From 3b150486c25f9e6668e4f5054d2ba263c349badb Mon Sep 17 00:00:00 2001 From: Ajin Cherian Date: Wed, 25 May 2022 05:37:53 -0400 Subject: [PATCH v5 3/3] Add support for drop tables in logical replication. Change the pubaction from 'create' to 'ddl'. Also add elements relid and cmdtype to the ddl message xlog and logical message. --- src/backend/catalog/pg_publication.c | 1 + src/backend/commands/ddl_deparse.c | 20 ++ src/backend/commands/event_trigger.c | 68 +++++- src/backend/commands/publicationcmds.c | 79 ++++--- src/backend/replication/logical/ddlmessage.c | 4 +- src/backend/replication/logical/logical.c | 17 +- src/backend/replication/logical/reorderbuffer.c | 21 +- src/backend/replication/pgoutput/pgoutput.c | 45 +++- src/backend/utils/cache/relcache.c | 2 +- src/bin/pg_dump/pg_dump.c | 20 +- src/bin/pg_dump/pg_dump.h | 2 +- src/bin/psql/describe.c | 20 +- src/include/catalog/pg_proc.dat | 3 + src/include/catalog/pg_publication.h | 4 +- src/include/replication/ddlmessage.h | 14 +- src/include/replication/output_plugin.h | 4 + src/include/replication/pgoutput.h | 1 + src/include/replication/reorderbuffer.h | 7 +- src/include/tcop/ddl_deparse.h | 1 + src/test/regress/expected/psql.out | 6 +- src/test/regress/expected/publication.out | 288 ++++++++++++------------ 21 files changed, 405 insertions(+), 222 deletions(-) diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c index 8c7fca6..20bf8c1 100644 --- a/src/backend/catalog/pg_publication.c +++ b/src/backend/catalog/pg_publication.c @@ -1005,6 +1005,7 @@ GetPublication(Oid pubid) pub->pubactions.pubupdate = pubform->pubupdate; pub->pubactions.pubdelete = pubform->pubdelete; pub->pubactions.pubtruncate = pubform->pubtruncate; + pub->pubactions.pubddl = pubform->pubddl; pub->pubviaroot = pubform->pubviaroot; ReleaseSysCache(tup); diff --git a/src/backend/commands/ddl_deparse.c b/src/backend/commands/ddl_deparse.c index ac92f10..bdf4ad3 100644 --- a/src/backend/commands/ddl_deparse.c +++ b/src/backend/commands/ddl_deparse.c @@ -1399,6 +1399,26 @@ deparse_simple_command(CollectedCommand *cmd) } char * +deparse_drop_table(const char *objidentity) +{ + StringInfoData str; + char *command; + ObjTree *stmt; + char *fmt; + Jsonb *jsonb; + + initStringInfo(&str); + fmt = psprintf("DROP TABLE IF EXISTS %%{objidentity}s"); + + stmt = new_objtree_VA(fmt, 1, "objidentity", ObjTypeString, + objidentity); + jsonb = objtree_to_jsonb(stmt); + command = JsonbToCString(&str, &jsonb->root, 128); + + return command; +} + +char * deparse_utility_command(CollectedCommand *cmd) { OverrideSearchPath *overridePath; diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c index 9c669c4..983f131 100644 --- a/src/backend/commands/event_trigger.c +++ b/src/backend/commands/event_trigger.c @@ -2190,9 +2190,50 @@ stringify_adefprivs_objtype(ObjectType objtype) * Deparse the ddl command and log it. */ Datum +publication_ddl_deparse_start(PG_FUNCTION_ARGS) +{ + EventTriggerData *trigdata; + char *command = psprintf("Drop table command start"); + DropStmt *stmt; + ListCell *cell1; + + if (!CALLED_AS_EVENT_TRIGGER(fcinfo)) + elog(ERROR, "not fired by event trigger manager"); + + trigdata = (EventTriggerData *) fcinfo->context; + stmt = (DropStmt *) trigdata->parsetree; + + /* extract the relid from the parse tree */ + foreach(cell1, stmt->objects) + { + Node *object = lfirst(cell1); + ObjectAddress address; + Relation relation = NULL; + + address = get_object_address(stmt->removeType, + object, + &relation, + AccessExclusiveLock, + true); + LogLogicalDDLMessage("deparse", address.objectId, DCT_DropStart, + command, strlen(command) + 1); + + if (relation) + table_close(relation, NoLock); + } + return PointerGetDatum(NULL); +} + +/* + * publication_ddl_deparse + * + * Deparse the ddl command and log it. + */ +Datum publication_ddl_deparse(PG_FUNCTION_ARGS) { ListCell *lc; + slist_iter iter; if (!CALLED_AS_EVENT_TRIGGER(fcinfo)) elog(ERROR, "not fired by event trigger manager"); @@ -2201,27 +2242,36 @@ publication_ddl_deparse(PG_FUNCTION_ARGS) { CollectedCommand *cmd = lfirst(lc); char *json_string; - static int i; if (cmd->type == SCT_Simple && !OidIsValid(cmd->d.simple.address.objectId)) continue; - /* - * Fixme: This is just for the development purpose and needs to be - * removed later. - */ - elog(LOG, "DDL command no. %d", ++i); - /* Deparse the DDL command and WAL log it to allow decoding of the same. */ json_string = deparse_utility_command(cmd); if (json_string == NULL) continue; - - LogLogicalDDLMessage("deparse", cmd->d.simple.address.objectId, cmd->type, + LogLogicalDDLMessage("deparse", cmd->d.simple.address.objectId, DCT_Create, json_string, strlen(json_string) + 1); } + slist_foreach(iter, &(currentEventTriggerState->SQLDropList)) + { + SQLDropObject *obj; + + obj = slist_container(SQLDropObject, next, iter.cur); + + if (strncmp(obj->objecttype, "table", 5) == 0) + { + char *command; + + command = deparse_drop_table(obj->objidentity); + + LogLogicalDDLMessage("deparse", obj->address.objectId, DCT_DropEnd, + command, strlen(command) + 1); + } + } + return PointerGetDatum(NULL); } diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c index fccd531..48a5601 100644 --- a/src/backend/commands/publicationcmds.c +++ b/src/backend/commands/publicationcmds.c @@ -97,7 +97,7 @@ parse_publication_options(ParseState *pstate, pubactions->pubupdate = true; pubactions->pubdelete = true; pubactions->pubtruncate = true; - pubactions->pubcreate = false; + pubactions->pubddl = false; *publish_via_partition_root = false; /* Parse options */ @@ -144,8 +144,8 @@ parse_publication_options(ParseState *pstate, pubactions->pubdelete = true; else if (strcmp(publish_opt, "truncate") == 0) pubactions->pubtruncate = true; - else if (strcmp(publish_opt, "create") == 0) - pubactions->pubcreate = true; + else if (strcmp(publish_opt, "ddl") == 0) + pubactions->pubddl = true; else ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), @@ -761,7 +761,7 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt) { Relation rel; ObjectAddress myself; - ObjectAddress referenced; + ObjectAddress referenced_start, referenced_end; Oid puboid; bool nulls[Natts_pg_publication]; Datum values[Natts_pg_publication]; @@ -826,8 +826,8 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt) BoolGetDatum(pubactions.pubdelete); values[Anum_pg_publication_pubtruncate - 1] = BoolGetDatum(pubactions.pubtruncate); - values[Anum_pg_publication_pubcreate - 1] = - BoolGetDatum(pubactions.pubcreate); + values[Anum_pg_publication_pubddl - 1] = + BoolGetDatum(pubactions.pubddl); values[Anum_pg_publication_pubviaroot - 1] = BoolGetDatum(publish_via_partition_root); @@ -900,33 +900,60 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt) * We need to enhance this once the approach for DDL replication is * finalized. */ - if (stmt->for_all_tables && pubactions.pubcreate) + if (pubactions.pubddl) { - CreateEventTrigStmt *ddl_trigg; - Node *args = NULL; - List *tags = NIL; - Oid event_trig_id; - char trigger_name[NAMEDATALEN]; + CreateEventTrigStmt *ddl_trigg_start, *ddl_trigg_end; + Node *end_arg1 = NULL; + Node *start_arg1 = NULL; + Node *arg2 = NULL; + List *end_tags = NIL; + List *start_tags = NIL; + Oid event_trig_start_id, event_trig_end_id; + char trigger_name_start[NAMEDATALEN]; + char trigger_name_end[NAMEDATALEN]; + + ddl_trigg_end = makeNode(CreateEventTrigStmt); + + snprintf(trigger_name_end, sizeof(trigger_name_end), "pg_deparse_trig_end_%u", + puboid); + ddl_trigg_end->trigname = pstrdup(trigger_name_end); + ddl_trigg_end->eventname = "ddl_command_end"; + ddl_trigg_end->funcname = SystemFuncName("publication_ddl_deparse"); + + end_arg1 = (Node *) makeString(pstrdup(GetCommandTagName(CMDTAG_DROP_TABLE))); + end_tags = list_make1(end_arg1); + + /* support create table only when publication is for all tables */ + if (stmt->for_all_tables) + { + arg2 = (Node *) makeString(pstrdup(GetCommandTagName(CMDTAG_CREATE_TABLE))); + end_tags = lappend(end_tags, arg2); + } + ddl_trigg_end->whenclause = list_make1(makeDefElem("tag", (Node *) end_tags, -1)); + event_trig_end_id = CreateEventTrigger(ddl_trigg_end); - ddl_trigg = makeNode(CreateEventTrigStmt); + ddl_trigg_start = makeNode(CreateEventTrigStmt); - snprintf(trigger_name, sizeof(trigger_name), "pg_deparse_trig_%u", + snprintf(trigger_name_start, sizeof(trigger_name_start), "pg_deparse_trig_start_%u", puboid); - ddl_trigg->trigname = pstrdup(trigger_name); - ddl_trigg->eventname = "ddl_command_end"; - ddl_trigg->funcname = SystemFuncName("publication_ddl_deparse"); + ddl_trigg_start->trigname = pstrdup(trigger_name_start); + ddl_trigg_start->eventname = "ddl_command_start"; + ddl_trigg_start->funcname = SystemFuncName("publication_ddl_deparse_start"); - args = (Node *) makeString(pstrdup(GetCommandTagName(CMDTAG_CREATE_TABLE))); - tags = list_make1(args); - ddl_trigg->whenclause = list_make1(makeDefElem("tag", (Node *) tags, -1)); - event_trig_id = CreateEventTrigger(ddl_trigg); + start_arg1 = (Node *) makeString(pstrdup(GetCommandTagName(CMDTAG_DROP_TABLE))); + start_tags = list_make1(start_arg1); + ddl_trigg_start->whenclause = list_make1(makeDefElem("tag", (Node *) start_tags, -1)); + event_trig_start_id = CreateEventTrigger(ddl_trigg_start); /* - * Register the event trigger as internally dependent on the + * Register the event triggers as internally dependent on the * publication. */ - ObjectAddressSet(referenced, EventTriggerRelationId, event_trig_id); - recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL); + ObjectAddressSet(referenced_end, EventTriggerRelationId, event_trig_end_id); + recordDependencyOn(&referenced_end, &myself, DEPENDENCY_INTERNAL); + + ObjectAddressSet(referenced_start, EventTriggerRelationId, event_trig_start_id); + recordDependencyOn(&referenced_start, &myself, DEPENDENCY_INTERNAL); } table_close(rel, RowExclusiveLock); @@ -1070,8 +1097,8 @@ AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt, values[Anum_pg_publication_pubtruncate - 1] = BoolGetDatum(pubactions.pubtruncate); replaces[Anum_pg_publication_pubtruncate - 1] = true; - values[Anum_pg_publication_pubcreate - 1] = BoolGetDatum(pubactions.pubcreate); - replaces[Anum_pg_publication_pubcreate - 1] = true; + values[Anum_pg_publication_pubddl - 1] = BoolGetDatum(pubactions.pubddl); + replaces[Anum_pg_publication_pubddl - 1] = true; } if (publish_via_partition_root_given) diff --git a/src/backend/replication/logical/ddlmessage.c b/src/backend/replication/logical/ddlmessage.c index c40cd62..5093523 100644 --- a/src/backend/replication/logical/ddlmessage.c +++ b/src/backend/replication/logical/ddlmessage.c @@ -42,7 +42,7 @@ * Write logical decoding DDL message into XLog. */ XLogRecPtr -LogLogicalDDLMessage(const char *prefix, Oid relid, NodeTag cmdtype, +LogLogicalDDLMessage(const char *prefix, Oid relid, DeparsedCommandType cmdtype, const char *message, size_t size) { xl_logical_ddl_message xlrec; @@ -57,6 +57,8 @@ LogLogicalDDLMessage(const char *prefix, Oid relid, NodeTag cmdtype, /* trailing zero is critical; see logicalddlmsg_desc */ xlrec.prefix_size = strlen(prefix) + 1; xlrec.message_size = size; + xlrec.relid = relid; + xlrec.cmdtype = cmdtype; XLogBeginInsert(); XLogRegisterData((char *) &xlrec, SizeOfLogicalDDLMessage); diff --git a/src/backend/replication/logical/logical.c b/src/backend/replication/logical/logical.c index d59017b..98969c7 100644 --- a/src/backend/replication/logical/logical.c +++ b/src/backend/replication/logical/logical.c @@ -33,6 +33,7 @@ #include "fmgr.h" #include "miscadmin.h" #include "pgstat.h" +#include "replication/ddlmessage.h" #include "replication/decode.h" #include "replication/logical.h" #include "replication/origin.h" @@ -75,6 +76,7 @@ static void message_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, const char *prefix, Size message_size, const char *message); static void ddlmessage_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, XLogRecPtr message_lsn, const char *prefix, + Oid relid, DeparsedCommandType cmdtype, Size message_size, const char *message); /* streaming callbacks */ @@ -96,6 +98,7 @@ static void stream_message_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *tx static void stream_ddlmessage_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, XLogRecPtr message_lsn, const char *prefix, + Oid relid, DeparsedCommandType cmdtype, Size message_size, const char *message); static void stream_truncate_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, int nrelations, Relation relations[], ReorderBufferChange *change); @@ -1233,7 +1236,8 @@ message_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, static void ddlmessage_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, XLogRecPtr message_lsn, - const char *prefix, Size message_size, + const char *prefix, Oid relid, DeparsedCommandType cmdtype, + Size message_size, const char *message) { LogicalDecodingContext *ctx = cache->private_data; @@ -1260,8 +1264,8 @@ ddlmessage_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, ctx->write_location = message_lsn; /* do the actual work: call callback */ - ctx->callbacks.ddlmessage_cb(ctx, txn, message_lsn, prefix, message_size, - message); + ctx->callbacks.ddlmessage_cb(ctx, txn, message_lsn, prefix, relid, cmdtype, + message_size, message); /* Pop the error context stack */ error_context_stack = errcallback.previous; @@ -1585,7 +1589,8 @@ stream_message_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, static void stream_ddlmessage_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, XLogRecPtr message_lsn, - const char *prefix, Size message_size, + const char *prefix, Oid relid, DeparsedCommandType cmdtype, + Size message_size, const char *message) { LogicalDecodingContext *ctx = cache->private_data; @@ -1616,8 +1621,8 @@ stream_ddlmessage_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, ctx->write_location = message_lsn; /* do the actual work: call callback */ - ctx->callbacks.stream_ddlmessage_cb(ctx, txn, message_lsn, prefix, message_size, - message); + ctx->callbacks.stream_ddlmessage_cb(ctx, txn, message_lsn, prefix, relid, + cmdtype, message_size, message); /* Pop the error context stack */ error_context_stack = errcallback.previous; diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c index ac146ba..346e19e 100644 --- a/src/backend/replication/logical/reorderbuffer.c +++ b/src/backend/replication/logical/reorderbuffer.c @@ -94,6 +94,7 @@ #include "lib/binaryheap.h" #include "miscadmin.h" #include "pgstat.h" +#include "replication/ddlmessage.h" #include "replication/logical.h" #include "replication/reorderbuffer.h" #include "replication/slot.h" @@ -881,7 +882,7 @@ void ReorderBufferQueueDDLMessage(ReorderBuffer *rb, TransactionId xid, XLogRecPtr lsn, const char *prefix, Size message_size, const char *message, - Oid relid, NodeTag cmdtype) + Oid relid, DeparsedCommandType cmdtype) { MemoryContext oldcontext; ReorderBufferChange *change; @@ -2005,11 +2006,15 @@ ReorderBufferApplyDDLMessage(ReorderBuffer *rb, ReorderBufferTXN *txn, if (streaming) rb->stream_ddlmessage(rb, txn, change->lsn, change->data.ddlmsg.prefix, + change->data.ddlmsg.relid, + change->data.ddlmsg.cmdtype, change->data.ddlmsg.message_size, change->data.ddlmsg.message); else rb->ddlmessage(rb, txn, change->lsn, change->data.ddlmsg.prefix, + change->data.ddlmsg.relid, + change->data.ddlmsg.cmdtype, change->data.ddlmsg.message_size, change->data.ddlmsg.message); } @@ -3777,7 +3782,7 @@ ReorderBufferSerializeChange(ReorderBuffer *rb, ReorderBufferTXN *txn, Size prefix_size = strlen(change->data.ddlmsg.prefix) + 1; sz += prefix_size + change->data.ddlmsg.message_size + - sizeof(Size) + sizeof(Size); + sizeof(Size) + sizeof(Oid) + sizeof(int) + sizeof(Size); ReorderBufferSerializeReserve(rb, sz); data = ((char *) rb->outbuf) + sizeof(ReorderBufferDiskChange); @@ -3785,9 +3790,13 @@ ReorderBufferSerializeChange(ReorderBuffer *rb, ReorderBufferTXN *txn, /* might have been reallocated above */ ondisk = (ReorderBufferDiskChange *) rb->outbuf; - /* write the prefix including the size */ + /* write the prefix, relid and cmdtype including the size */ memcpy(data, &prefix_size, sizeof(Size)); data += sizeof(Size); + memcpy(data, &change->data.ddlmsg.relid, sizeof(Oid)); + data += sizeof(Oid); + memcpy(data, &change->data.ddlmsg.cmdtype, sizeof(int)); + data += sizeof(int); memcpy(data, change->data.ddlmsg.prefix, prefix_size); data += prefix_size; @@ -4120,7 +4129,7 @@ ReorderBufferChangeSize(ReorderBufferChange *change) Size prefix_size = strlen(change->data.ddlmsg.prefix) + 1; sz += prefix_size + change->data.ddlmsg.message_size + - sizeof(Size) + sizeof(Size); + sizeof(Size) + sizeof(Size) + sizeof(Oid) + sizeof(int); break; } @@ -4405,6 +4414,10 @@ ReorderBufferRestoreChange(ReorderBuffer *rb, ReorderBufferTXN *txn, /* read prefix */ memcpy(&prefix_size, data, sizeof(Size)); data += sizeof(Size); + memcpy(&change->data.ddlmsg.relid, data, sizeof(Oid)); + data += sizeof(Oid); + memcpy(&change->data.ddlmsg.cmdtype, data, sizeof(int)); + data += sizeof(int); change->data.ddlmsg.prefix = MemoryContextAlloc(rb->context, prefix_size); memcpy(change->data.ddlmsg.prefix, data, prefix_size); Assert(change->data.ddlmsg.prefix[prefix_size - 1] == '\0'); diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c index a8deb33..b158580 100644 --- a/src/backend/replication/pgoutput/pgoutput.c +++ b/src/backend/replication/pgoutput/pgoutput.c @@ -56,7 +56,8 @@ static void pgoutput_message(LogicalDecodingContext *ctx, Size sz, const char *message); static void pgoutput_ddlmessage(LogicalDecodingContext *ctx, ReorderBufferTXN *txn, XLogRecPtr message_lsn, - const char *prefix, Size sz, const char *message); + const char *prefix, Oid relid, DeparsedCommandType cmdtype, + Size sz, const char *message); static bool pgoutput_origin_filter(LogicalDecodingContext *ctx, RepOriginId origin_id); static void pgoutput_begin_prepare_txn(LogicalDecodingContext *ctx, @@ -485,6 +486,7 @@ pgoutput_startup(LogicalDecodingContext *ctx, OutputPluginOptions *opt, /* Init publication state. */ data->publications = NIL; + data->deleted_relids = NIL; publications_valid = false; CacheRegisterSyscacheCallback(PUBLICATIONOID, publication_invalidation_cb, @@ -1705,10 +1707,14 @@ pgoutput_message(LogicalDecodingContext *ctx, ReorderBufferTXN *txn, static void pgoutput_ddlmessage(LogicalDecodingContext *ctx, ReorderBufferTXN *txn, XLogRecPtr message_lsn, - const char *prefix, Size sz, const char *message) + const char *prefix, Oid relid, DeparsedCommandType cmdtype, + Size sz, const char *message) { + PGOutputData *data = (PGOutputData *) ctx->output_plugin_private; PGOutputTxnData *txndata = (PGOutputTxnData *) txn->output_plugin_private; + Relation relation = NULL; TransactionId xid = InvalidTransactionId; + RelationSyncEntry *relentry; /* * Remember the xid for the message in streaming mode. See @@ -1717,6 +1723,35 @@ pgoutput_ddlmessage(LogicalDecodingContext *ctx, ReorderBufferTXN *txn, if (in_streaming) xid = txn->xid; + /* + * On DROP start, add the relid to a deleted_relid list if the relid + * is part of a publication that supports ddl publication. We need this because + * on DROP end, the relid will no longer be valid. Later on Drop end, verify that + * the drop is for a relid that is on the deleted_rid list, and only then send + * the ddl message. + */ + + if ((cmdtype == DCT_DropStart)) + { + relation = RelationIdGetRelation(relid); + Assert(relation); + relentry = get_rel_sync_entry(data, relation); + if (relentry->pubactions.pubddl) + { + data->deleted_relids = lappend_oid(data->deleted_relids, relid); + } + return; + } + + if ((cmdtype == DCT_DropEnd)) + { + if(!list_member_oid(data->deleted_relids, relid)) + return; + else + { + data->deleted_relids = list_delete_oid(data->deleted_relids, relid); + } + } /* Send BEGIN if we haven't yet */ if (txndata && !txndata->sent_begin_txn) @@ -2017,7 +2052,8 @@ get_rel_sync_entry(PGOutputData *data, Relation relation) entry->schema_sent = false; entry->streamed_txns = NIL; entry->pubactions.pubinsert = entry->pubactions.pubupdate = - entry->pubactions.pubdelete = entry->pubactions.pubtruncate = false; + entry->pubactions.pubdelete = entry->pubactions.pubtruncate = + entry->pubactions.pubddl = false; entry->new_slot = NULL; entry->old_slot = NULL; memset(entry->exprstate, 0, sizeof(entry->exprstate)); @@ -2075,6 +2111,7 @@ get_rel_sync_entry(PGOutputData *data, Relation relation) entry->pubactions.pubupdate = false; entry->pubactions.pubdelete = false; entry->pubactions.pubtruncate = false; + entry->pubactions.pubddl = false; /* * Tuple slots cleanups. (Will be rebuilt later if needed). @@ -2188,6 +2225,7 @@ get_rel_sync_entry(PGOutputData *data, Relation relation) entry->pubactions.pubupdate |= pub->pubactions.pubupdate; entry->pubactions.pubdelete |= pub->pubactions.pubdelete; entry->pubactions.pubtruncate |= pub->pubactions.pubtruncate; + entry->pubactions.pubddl |= pub->pubactions.pubddl; /* * We want to publish the changes as the top-most ancestor @@ -2373,6 +2411,7 @@ rel_sync_cache_publication_cb(Datum arg, int cacheid, uint32 hashvalue) { entry->replicate_valid = false; } + } /* Send Replication origin */ diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 586d6f9..7b51fb4 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -5633,7 +5633,7 @@ RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc) pubdesc->pubactions.pubupdate |= pubform->pubupdate; pubdesc->pubactions.pubdelete |= pubform->pubdelete; pubdesc->pubactions.pubtruncate |= pubform->pubtruncate; - pubdesc->pubactions.pubcreate |= pubform->pubcreate; + pubdesc->pubactions.pubddl |= pubform->pubddl; /* * Check if all columns referenced in the filter expression are part diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 7d9c6eb..030d491 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -3867,7 +3867,7 @@ getPublications(Archive *fout, int *numPublications) int i_pubupdate; int i_pubdelete; int i_pubtruncate; - int i_pubcreate; + int i_pubddl; int i_pubviaroot; int i, ntups; @@ -3887,25 +3887,25 @@ getPublications(Archive *fout, int *numPublications) appendPQExpBuffer(query, "SELECT p.tableoid, p.oid, p.pubname, " "p.pubowner, " - "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, p.pubcreate, p.pubviaroot " + "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, p.pubddl, p.pubviaroot " "FROM pg_publication p"); else if (fout->remoteVersion >= 130000) appendPQExpBuffer(query, "SELECT p.tableoid, p.oid, p.pubname, " "p.pubowner, " - "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, false as p.pubcreate, p.pubviaroot " + "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, false as p.pubddl, p.pubviaroot " "FROM pg_publication p"); else if (fout->remoteVersion >= 110000) appendPQExpBuffer(query, "SELECT p.tableoid, p.oid, p.pubname, " "p.pubowner, " - "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, false as p.pubcreate, false AS pubviaroot " + "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, false as p.pubddl, false AS pubviaroot " "FROM pg_publication p"); else appendPQExpBuffer(query, "SELECT p.tableoid, p.oid, p.pubname, " "p.pubowner, " - "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, false AS pubtruncate, false as p.pubcreate, false AS pubviaroot " + "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, false AS pubtruncate, false as p.pubddl, false AS pubviaroot " "FROM pg_publication p"); res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); @@ -3921,7 +3921,7 @@ getPublications(Archive *fout, int *numPublications) i_pubupdate = PQfnumber(res, "pubupdate"); i_pubdelete = PQfnumber(res, "pubdelete"); i_pubtruncate = PQfnumber(res, "pubtruncate"); - i_pubcreate = PQfnumber(res, "pubcreate"); + i_pubddl = PQfnumber(res, "pubddl"); i_pubviaroot = PQfnumber(res, "pubviaroot"); pubinfo = pg_malloc(ntups * sizeof(PublicationInfo)); @@ -3945,8 +3945,8 @@ getPublications(Archive *fout, int *numPublications) (strcmp(PQgetvalue(res, i, i_pubdelete), "t") == 0); pubinfo[i].pubtruncate = (strcmp(PQgetvalue(res, i, i_pubtruncate), "t") == 0); - pubinfo[i].pubcreate = - (strcmp(PQgetvalue(res, i, i_pubcreate), "t") == 0); + pubinfo[i].pubddl = + (strcmp(PQgetvalue(res, i, i_pubddl), "t") == 0); pubinfo[i].pubviaroot = (strcmp(PQgetvalue(res, i, i_pubviaroot), "t") == 0); @@ -4026,12 +4026,12 @@ dumpPublication(Archive *fout, const PublicationInfo *pubinfo) first = false; } - if (pubinfo->pubcreate) + if (pubinfo->pubddl) { if (!first) appendPQExpBufferStr(query, ", "); - appendPQExpBufferStr(query, "create"); + appendPQExpBufferStr(query, "ddl"); first = false; } diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h index 170271e..69b94ae 100644 --- a/src/bin/pg_dump/pg_dump.h +++ b/src/bin/pg_dump/pg_dump.h @@ -620,7 +620,7 @@ typedef struct _PublicationInfo bool pubdelete; bool pubtruncate; bool pubviaroot; - bool pubcreate; + bool pubddl; } PublicationInfo; /* diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 32cae61..fe28abb 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -6087,8 +6087,8 @@ listPublications(const char *pattern) gettext_noop("Via root")); if (pset.sversion >= 140000) appendPQExpBuffer(&buf, - ",\n pubcreate AS \"%s\"", - gettext_noop("Creates")); + ",\n pubddl AS \"%s\"", + gettext_noop("DDLs")); appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_publication\n"); @@ -6176,7 +6176,7 @@ describePublications(const char *pattern) PGresult *res; bool has_pubtruncate; bool has_pubviaroot; - bool has_pubcreate; + bool has_pubddl; PQExpBufferData title; printTableContent cont; @@ -6193,7 +6193,7 @@ describePublications(const char *pattern) has_pubtruncate = (pset.sversion >= 110000); has_pubviaroot = (pset.sversion >= 130000); - has_pubcreate = (pset.sversion >= 150000); + has_pubddl = (pset.sversion >= 150000); initPQExpBuffer(&buf); @@ -6207,9 +6207,9 @@ describePublications(const char *pattern) if (has_pubviaroot) appendPQExpBufferStr(&buf, ", pubviaroot"); - if (has_pubcreate) + if (has_pubddl) appendPQExpBufferStr(&buf, - ", pubcreate"); + ", pubddl"); appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_publication\n"); @@ -6258,7 +6258,7 @@ describePublications(const char *pattern) ncols++; if (has_pubviaroot) ncols++; - if (has_pubcreate) + if (has_pubddl) ncols++; initPQExpBuffer(&title); @@ -6274,8 +6274,8 @@ describePublications(const char *pattern) printTableAddHeader(&cont, gettext_noop("Truncates"), true, align); if (has_pubviaroot) printTableAddHeader(&cont, gettext_noop("Via root"), true, align); - if (has_pubcreate) - printTableAddHeader(&cont, gettext_noop("Creates"), true, align); + if (has_pubddl) + printTableAddHeader(&cont, gettext_noop("DDLs"), true, align); printTableAddCell(&cont, PQgetvalue(res, i, 2), false, false); printTableAddCell(&cont, PQgetvalue(res, i, 3), false, false); @@ -6286,7 +6286,7 @@ describePublications(const char *pattern) printTableAddCell(&cont, PQgetvalue(res, i, 7), false, false); if (has_pubviaroot) printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false); - if (has_pubcreate) + if (has_pubddl) printTableAddCell(&cont, PQgetvalue(res, i, 9), false, false); if (!puballtables) diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index cf39fee..ffcd83c 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -11893,5 +11893,8 @@ { oid => '4644', descr => 'trigger for ddl command deparse', proname => 'publication_ddl_deparse', prorettype => 'event_trigger', proargtypes => '', prosrc => 'publication_ddl_deparse' }, +{ oid => '4645', descr => 'trigger for ddl command deparse start', + proname => 'publication_ddl_deparse_start', prorettype => 'event_trigger', + proargtypes => '', prosrc => 'publication_ddl_deparse_start' }, ] diff --git a/src/include/catalog/pg_publication.h b/src/include/catalog/pg_publication.h index bfa63cd..606c009 100644 --- a/src/include/catalog/pg_publication.h +++ b/src/include/catalog/pg_publication.h @@ -56,7 +56,7 @@ CATALOG(pg_publication,6104,PublicationRelationId) bool pubviaroot; /* true if table creations are published */ - bool pubcreate; + bool pubddl; } FormData_pg_publication; /* ---------------- @@ -75,7 +75,7 @@ typedef struct PublicationActions bool pubupdate; bool pubdelete; bool pubtruncate; - bool pubcreate; + bool pubddl; } PublicationActions; typedef struct PublicationDesc diff --git a/src/include/replication/ddlmessage.h b/src/include/replication/ddlmessage.h index 8d9be7c..172d091 100644 --- a/src/include/replication/ddlmessage.h +++ b/src/include/replication/ddlmessage.h @@ -15,6 +15,18 @@ #include "access/xlogreader.h" #include "nodes/nodes.h" + +/* + * Support for keeping track of deparsed commands. + */ +typedef enum DeparsedCommandType +{ + DCT_Create, + DCT_DropStart, + DCT_DropEnd, + DCT_Alter +} DeparsedCommandType; + /* * Generic logical decoding DDL message wal record. */ @@ -33,7 +45,7 @@ typedef struct xl_logical_ddl_message #define SizeOfLogicalDDLMessage (offsetof(xl_logical_ddl_message, message)) -extern XLogRecPtr LogLogicalDDLMessage(const char *prefix, Oid relid, NodeTag cmdtype, +extern XLogRecPtr LogLogicalDDLMessage(const char *prefix, Oid relid, DeparsedCommandType cmdtype, const char *ddl_message, size_t size); /* RMGR API*/ diff --git a/src/include/replication/output_plugin.h b/src/include/replication/output_plugin.h index fa7a8b8..933d297 100644 --- a/src/include/replication/output_plugin.h +++ b/src/include/replication/output_plugin.h @@ -95,6 +95,8 @@ typedef void (*LogicalDecodeDDLMessageCB) (struct LogicalDecodingContext *ctx, ReorderBufferTXN *txn, XLogRecPtr message_lsn, const char *prefix, + Oid relid, + DeparsedCommandType cmdtype, Size message_size, const char *message); @@ -217,6 +219,8 @@ typedef void (*LogicalDecodeStreamDDLMessageCB) (struct LogicalDecodingContext * ReorderBufferTXN *txn, XLogRecPtr message_lsn, const char *prefix, + Oid relid, + DeparsedCommandType cmdtype, Size message_size, const char *message); diff --git a/src/include/replication/pgoutput.h b/src/include/replication/pgoutput.h index eafedd6..8ebcc12 100644 --- a/src/include/replication/pgoutput.h +++ b/src/include/replication/pgoutput.h @@ -25,6 +25,7 @@ typedef struct PGOutputData uint32 protocol_version; List *publication_names; List *publications; + List *deleted_relids; bool binary; bool streaming; bool messages; diff --git a/src/include/replication/reorderbuffer.h b/src/include/replication/reorderbuffer.h index 826c9ce..3664873 100644 --- a/src/include/replication/reorderbuffer.h +++ b/src/include/replication/reorderbuffer.h @@ -12,6 +12,7 @@ #include "access/htup_details.h" #include "lib/ilist.h" #include "nodes/nodes.h" +#include "replication/ddlmessage.h" #include "storage/sinval.h" #include "utils/hsearch.h" #include "utils/relcache.h" @@ -447,6 +448,8 @@ typedef void (*ReorderBufferDDLMessageCB) (ReorderBuffer *rb, ReorderBufferTXN *txn, XLogRecPtr message_lsn, const char *prefix, + Oid relid, + DeparsedCommandType cmdtype, Size sz, const char *message); @@ -522,6 +525,8 @@ typedef void (*ReorderBufferStreamDDLMessageCB) ( ReorderBufferTXN *txn, XLogRecPtr message_lsn, const char *prefix, + Oid relid, + DeparsedCommandType cmdtype, Size sz, const char *message); @@ -668,7 +673,7 @@ extern void ReorderBufferQueueMessage(ReorderBuffer *, TransactionId, Snapshot s Size message_size, const char *message); extern void ReorderBufferQueueDDLMessage(ReorderBuffer *, TransactionId, XLogRecPtr lsn, const char *prefix, Size message_size, - const char *message, Oid relid, NodeTag cmdtype); + const char *message, Oid relid, DeparsedCommandType cmdtype); extern void ReorderBufferCommit(ReorderBuffer *, TransactionId, XLogRecPtr commit_lsn, XLogRecPtr end_lsn, TimestampTz commit_time, RepOriginId origin_id, XLogRecPtr origin_lsn); diff --git a/src/include/tcop/ddl_deparse.h b/src/include/tcop/ddl_deparse.h index e979ee5..fb174d2 100644 --- a/src/include/tcop/ddl_deparse.h +++ b/src/include/tcop/ddl_deparse.h @@ -5,5 +5,6 @@ extern char *deparse_utility_command(CollectedCommand *cmd); extern char *ddl_deparse_json_to_string(char *jsonb); +extern char *deparse_drop_table(const char *objidentity); #endif /* DDL_DEPARSE_H */ diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out index a8a1239..b1921cc 100644 --- a/src/test/regress/expected/psql.out +++ b/src/test/regress/expected/psql.out @@ -5969,9 +5969,9 @@ List of schemas (0 rows) \dRp "no.such.publication" - List of publications - Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates -------+-------+------------+---------+---------+---------+-----------+----------+--------- + List of publications + Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +------+-------+------------+---------+---------+---------+-----------+----------+------ (0 rows) \dRs "no.such.subscription" diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out index 6e486cf..09b14e0 100644 --- a/src/test/regress/expected/publication.out +++ b/src/test/regress/expected/publication.out @@ -30,18 +30,18 @@ ERROR: conflicting or redundant options LINE 1: ...ub_xxx WITH (publish_via_partition_root = 'true', publish_vi... ^ \dRp - List of publications - Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------+--------------------------+------------+---------+---------+---------+-----------+----------+--------- + List of publications + Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------+--------------------------+------------+---------+---------+---------+-----------+----------+------ testpib_ins_trunct | regress_publication_user | f | t | f | f | f | f | f testpub_default | regress_publication_user | f | f | t | f | f | f | f (2 rows) ALTER PUBLICATION testpub_default SET (publish = 'insert, update, delete'); \dRp - List of publications - Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------+--------------------------+------------+---------+---------+---------+-----------+----------+--------- + List of publications + Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------+--------------------------+------------+---------+---------+---------+-----------+----------+------ testpib_ins_trunct | regress_publication_user | f | t | f | f | f | f | f testpub_default | regress_publication_user | f | t | t | t | f | f | f (2 rows) @@ -87,9 +87,9 @@ RESET client_min_messages; -- should be able to add schema to 'FOR TABLE' publication ALTER PUBLICATION testpub_fortable ADD ALL TABLES IN SCHEMA pub_test; \dRp+ testpub_fortable - Publication testpub_fortable - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub_fortable + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables: "public.testpub_tbl1" @@ -99,9 +99,9 @@ Tables from schemas: -- should be able to drop schema from 'FOR TABLE' publication ALTER PUBLICATION testpub_fortable DROP ALL TABLES IN SCHEMA pub_test; \dRp+ testpub_fortable - Publication testpub_fortable - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub_fortable + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables: "public.testpub_tbl1" @@ -109,9 +109,9 @@ Tables: -- should be able to set schema to 'FOR TABLE' publication ALTER PUBLICATION testpub_fortable SET ALL TABLES IN SCHEMA pub_test; \dRp+ testpub_fortable - Publication testpub_fortable - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub_fortable + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables from schemas: "pub_test" @@ -134,9 +134,9 @@ ERROR: relation "testpub_nopk" is not part of the publication -- should be able to set table to schema publication ALTER PUBLICATION testpub_forschema SET TABLE pub_test.testpub_nopk; \dRp+ testpub_forschema - Publication testpub_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables: "pub_test.testpub_nopk" @@ -159,9 +159,9 @@ Publications: "testpub_foralltables" \dRp+ testpub_foralltables - Publication testpub_foralltables - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub_foralltables + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | t | t | t | f | f | f | f (1 row) @@ -174,18 +174,18 @@ CREATE PUBLICATION testpub3 FOR TABLE testpub_tbl3; CREATE PUBLICATION testpub4 FOR TABLE ONLY testpub_tbl3; RESET client_min_messages; \dRp+ testpub3 - Publication testpub3 - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub3 + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables: "public.testpub_tbl3" "public.testpub_tbl3a" \dRp+ testpub4 - Publication testpub4 - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub4 + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables: "public.testpub_tbl3" @@ -207,9 +207,9 @@ UPDATE testpub_parted1 SET a = 1; -- only parent is listed as being in publication, not the partition ALTER PUBLICATION testpub_forparted ADD TABLE testpub_parted; \dRp+ testpub_forparted - Publication testpub_forparted - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub_forparted + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables: "public.testpub_parted" @@ -223,9 +223,9 @@ ALTER TABLE testpub_parted DETACH PARTITION testpub_parted1; UPDATE testpub_parted1 SET a = 1; ALTER PUBLICATION testpub_forparted SET (publish_via_partition_root = true); \dRp+ testpub_forparted - Publication testpub_forparted - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub_forparted + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | t | f Tables: "public.testpub_parted" @@ -255,9 +255,9 @@ SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub5 FOR TABLE testpub_rf_tbl1, testpub_rf_tbl2 WHERE (c <> 'test' AND d < 5) WITH (publish = 'insert'); RESET client_min_messages; \dRp+ testpub5 - Publication testpub5 - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub5 + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | f | f | f | f | f Tables: "public.testpub_rf_tbl1" @@ -271,9 +271,9 @@ Tables: ALTER PUBLICATION testpub5 ADD TABLE testpub_rf_tbl3 WHERE (e > 1000 AND e < 2000); \dRp+ testpub5 - Publication testpub5 - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub5 + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | f | f | f | f | f Tables: "public.testpub_rf_tbl1" @@ -290,9 +290,9 @@ Publications: ALTER PUBLICATION testpub5 DROP TABLE testpub_rf_tbl2; \dRp+ testpub5 - Publication testpub5 - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub5 + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | f | f | f | f | f Tables: "public.testpub_rf_tbl1" @@ -301,9 +301,9 @@ Tables: -- remove testpub_rf_tbl1 and add testpub_rf_tbl3 again (another WHERE expression) ALTER PUBLICATION testpub5 SET TABLE testpub_rf_tbl3 WHERE (e > 300 AND e < 500); \dRp+ testpub5 - Publication testpub5 - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub5 + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | f | f | f | f | f Tables: "public.testpub_rf_tbl3" WHERE ((e > 300) AND (e < 500)) @@ -337,9 +337,9 @@ SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_syntax1 FOR TABLE testpub_rf_tbl1, ONLY testpub_rf_tbl3 WHERE (e < 999) WITH (publish = 'insert'); RESET client_min_messages; \dRp+ testpub_syntax1 - Publication testpub_syntax1 - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub_syntax1 + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | f | f | f | f | f Tables: "public.testpub_rf_tbl1" @@ -350,9 +350,9 @@ SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_syntax2 FOR TABLE testpub_rf_tbl1, testpub_rf_schema1.testpub_rf_tbl5 WHERE (h < 999) WITH (publish = 'insert'); RESET client_min_messages; \dRp+ testpub_syntax2 - Publication testpub_syntax2 - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub_syntax2 + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | f | f | f | f | f Tables: "public.testpub_rf_tbl1" @@ -676,9 +676,9 @@ CREATE PUBLICATION testpub_table_ins WITH (publish = 'insert, truncate'); RESET client_min_messages; ALTER PUBLICATION testpub_table_ins ADD TABLE testpub_tbl5 (a); -- ok \dRp+ testpub_table_ins - Publication testpub_table_ins - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub_table_ins + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | f | f | t | f | f Tables: "public.testpub_tbl5" (a) @@ -821,9 +821,9 @@ CREATE TABLE testpub_tbl_both_filters (a int, b int, c int, PRIMARY KEY (a,c)); ALTER TABLE testpub_tbl_both_filters REPLICA IDENTITY USING INDEX testpub_tbl_both_filters_pkey; ALTER PUBLICATION testpub_both_filters ADD TABLE testpub_tbl_both_filters (a,c) WHERE (c != 1); \dRp+ testpub_both_filters - Publication testpub_both_filters - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub_both_filters + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables: "public.testpub_tbl_both_filters" (a, c) WHERE (c <> 1) @@ -1029,9 +1029,9 @@ ERROR: relation "testpub_tbl1" is already member of publication "testpub_fortbl CREATE PUBLICATION testpub_fortbl FOR TABLE testpub_tbl1; ERROR: publication "testpub_fortbl" already exists \dRp+ testpub_fortbl - Publication testpub_fortbl - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub_fortbl + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables: "pub_test.testpub_nopk" @@ -1070,9 +1070,9 @@ Publications: "testpub_fortbl" \dRp+ testpub_default - Publication testpub_default - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub_default + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | f | f | f Tables: "pub_test.testpub_nopk" @@ -1151,9 +1151,9 @@ REVOKE CREATE ON DATABASE regression FROM regress_publication_user2; DROP TABLE testpub_parted; DROP TABLE testpub_tbl1; \dRp+ testpub_default - Publication testpub_default - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub_default + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | f | f | f (1 row) @@ -1164,9 +1164,9 @@ ERROR: must be owner of publication testpub_default RESET ROLE; ALTER PUBLICATION testpub_default RENAME TO testpub_foo; \dRp testpub_foo - List of publications - Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates --------------+--------------------------+------------+---------+---------+---------+-----------+----------+--------- + List of publications + Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +-------------+--------------------------+------------+---------+---------+---------+-----------+----------+------ testpub_foo | regress_publication_user | f | t | t | t | f | f | f (1 row) @@ -1174,9 +1174,9 @@ ALTER PUBLICATION testpub_default RENAME TO testpub_foo; ALTER PUBLICATION testpub_foo RENAME TO testpub_default; ALTER PUBLICATION testpub_default OWNER TO regress_publication_user2; \dRp testpub_default - List of publications - Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ------------------+---------------------------+------------+---------+---------+---------+-----------+----------+--------- + List of publications + Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +-----------------+---------------------------+------------+---------+---------+---------+-----------+----------+------ testpub_default | regress_publication_user2 | f | t | t | t | f | f | f (1 row) @@ -1193,18 +1193,18 @@ CREATE TABLE "CURRENT_SCHEMA"."CURRENT_SCHEMA"(id int); SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub1_forschema FOR ALL TABLES IN SCHEMA pub_test1; \dRp+ testpub1_forschema - Publication testpub1_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub1_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables from schemas: "pub_test1" CREATE PUBLICATION testpub2_forschema FOR ALL TABLES IN SCHEMA pub_test1, pub_test2, pub_test3; \dRp+ testpub2_forschema - Publication testpub2_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub2_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables from schemas: "pub_test1" @@ -1219,43 +1219,43 @@ CREATE PUBLICATION testpub6_forschema FOR ALL TABLES IN SCHEMA "CURRENT_SCHEMA", CREATE PUBLICATION testpub_fortable FOR TABLE "CURRENT_SCHEMA"."CURRENT_SCHEMA"; RESET client_min_messages; \dRp+ testpub3_forschema - Publication testpub3_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub3_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables from schemas: "public" \dRp+ testpub4_forschema - Publication testpub4_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub4_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables from schemas: "CURRENT_SCHEMA" \dRp+ testpub5_forschema - Publication testpub5_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub5_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables from schemas: "CURRENT_SCHEMA" "public" \dRp+ testpub6_forschema - Publication testpub6_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub6_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables from schemas: "CURRENT_SCHEMA" "public" \dRp+ testpub_fortable - Publication testpub_fortable - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub_fortable + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables: "CURRENT_SCHEMA.CURRENT_SCHEMA" @@ -1290,9 +1290,9 @@ ERROR: schema "testpub_view" does not exist -- dropping the schema should reflect the change in publication DROP SCHEMA pub_test3; \dRp+ testpub2_forschema - Publication testpub2_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub2_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables from schemas: "pub_test1" @@ -1301,9 +1301,9 @@ Tables from schemas: -- renaming the schema should reflect the change in publication ALTER SCHEMA pub_test1 RENAME to pub_test1_renamed; \dRp+ testpub2_forschema - Publication testpub2_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub2_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables from schemas: "pub_test1_renamed" @@ -1311,9 +1311,9 @@ Tables from schemas: ALTER SCHEMA pub_test1_renamed RENAME to pub_test1; \dRp+ testpub2_forschema - Publication testpub2_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub2_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables from schemas: "pub_test1" @@ -1322,9 +1322,9 @@ Tables from schemas: -- alter publication add schema ALTER PUBLICATION testpub1_forschema ADD ALL TABLES IN SCHEMA pub_test2; \dRp+ testpub1_forschema - Publication testpub1_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub1_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables from schemas: "pub_test1" @@ -1334,9 +1334,9 @@ Tables from schemas: ALTER PUBLICATION testpub1_forschema ADD ALL TABLES IN SCHEMA non_existent_schema; ERROR: schema "non_existent_schema" does not exist \dRp+ testpub1_forschema - Publication testpub1_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub1_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables from schemas: "pub_test1" @@ -1346,9 +1346,9 @@ Tables from schemas: ALTER PUBLICATION testpub1_forschema ADD ALL TABLES IN SCHEMA pub_test1; ERROR: schema "pub_test1" is already member of publication "testpub1_forschema" \dRp+ testpub1_forschema - Publication testpub1_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub1_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables from schemas: "pub_test1" @@ -1357,9 +1357,9 @@ Tables from schemas: -- alter publication drop schema ALTER PUBLICATION testpub1_forschema DROP ALL TABLES IN SCHEMA pub_test2; \dRp+ testpub1_forschema - Publication testpub1_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub1_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables from schemas: "pub_test1" @@ -1368,9 +1368,9 @@ Tables from schemas: ALTER PUBLICATION testpub1_forschema DROP ALL TABLES IN SCHEMA pub_test2; ERROR: tables from schema "pub_test2" are not part of the publication \dRp+ testpub1_forschema - Publication testpub1_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub1_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables from schemas: "pub_test1" @@ -1379,9 +1379,9 @@ Tables from schemas: ALTER PUBLICATION testpub1_forschema DROP ALL TABLES IN SCHEMA non_existent_schema; ERROR: schema "non_existent_schema" does not exist \dRp+ testpub1_forschema - Publication testpub1_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub1_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables from schemas: "pub_test1" @@ -1389,18 +1389,18 @@ Tables from schemas: -- drop all schemas ALTER PUBLICATION testpub1_forschema DROP ALL TABLES IN SCHEMA pub_test1; \dRp+ testpub1_forschema - Publication testpub1_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub1_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f (1 row) -- alter publication set multiple schema ALTER PUBLICATION testpub1_forschema SET ALL TABLES IN SCHEMA pub_test1, pub_test2; \dRp+ testpub1_forschema - Publication testpub1_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub1_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables from schemas: "pub_test1" @@ -1410,9 +1410,9 @@ Tables from schemas: ALTER PUBLICATION testpub1_forschema SET ALL TABLES IN SCHEMA non_existent_schema; ERROR: schema "non_existent_schema" does not exist \dRp+ testpub1_forschema - Publication testpub1_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub1_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables from schemas: "pub_test1" @@ -1422,9 +1422,9 @@ Tables from schemas: -- removing the duplicate schemas ALTER PUBLICATION testpub1_forschema SET ALL TABLES IN SCHEMA pub_test1, pub_test1; \dRp+ testpub1_forschema - Publication testpub1_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub1_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables from schemas: "pub_test1" @@ -1504,17 +1504,17 @@ SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub3_forschema; RESET client_min_messages; \dRp+ testpub3_forschema - Publication testpub3_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub3_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f (1 row) ALTER PUBLICATION testpub3_forschema SET ALL TABLES IN SCHEMA pub_test1; \dRp+ testpub3_forschema - Publication testpub3_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub3_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables from schemas: "pub_test1" @@ -1525,9 +1525,9 @@ CREATE PUBLICATION testpub_forschema_fortable FOR ALL TABLES IN SCHEMA pub_test1 CREATE PUBLICATION testpub_fortable_forschema FOR TABLE pub_test2.tbl1, ALL TABLES IN SCHEMA pub_test1; RESET client_min_messages; \dRp+ testpub_forschema_fortable - Publication testpub_forschema_fortable - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub_forschema_fortable + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables: "pub_test2.tbl1" @@ -1535,9 +1535,9 @@ Tables from schemas: "pub_test1" \dRp+ testpub_fortable_forschema - Publication testpub_fortable_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | Creates ---------------------------+------------+---------+---------+---------+-----------+----------+--------- + Publication testpub_fortable_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root | DDLs +--------------------------+------------+---------+---------+---------+-----------+----------+------ regress_publication_user | f | t | t | t | t | f | f Tables: "pub_test2.tbl1" -- 1.8.3.1