From: Craig Ringer Date: Mon, 15 Dec 2014 10:42:39 +0000 (+0800) Subject: bdr: Prevent slot creation on output plugin if bdr ext missing X-Git-Tag: bdr-plugin/0.8.0~26 X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=2f0160f5f7d463ff52a9a50f30db2655895d1677;p=2ndquadrant_bdr.git bdr: Prevent slot creation on output plugin if bdr ext missing We shouldn't allow slot creation if the BDR extension is not installed in a database. --- diff --git a/bdr_output.c b/bdr_output.c index 57cdea0709..a9dc5051ab 100644 --- a/bdr_output.c +++ b/bdr_output.c @@ -219,12 +219,13 @@ bdr_req_param(const char *param) } /* - * Check bdr.bdr_nodes entry in local DB and if status != r, - * raise an error. + * Check bdr.bdr_nodes entry in local DB and if status != r + * and we're trying to begin logical replay, raise an error. * - * If this function returns it's safe to begin replay. + * Also prevents slot creation if the BDR extension isn't installed in the + * local node. * - * Must be called inside transaction. + * If this function returns it's safe to begin replay. */ static void bdr_ensure_node_ready() @@ -348,7 +349,7 @@ pg_decode_startup(LogicalDecodingContext * ctx, OutputPluginOptions *opt, bool i ListCell *option; BdrOutputData *data; Oid schema_oid; - bool tx_started = true; + bool tx_started = false; bdr_worker_type = BDR_WORKER_WALSENDER; @@ -462,6 +463,41 @@ pg_decode_startup(LogicalDecodingContext * ctx, OutputPluginOptions *opt, bool i } } + /* + * Ensure that the BDR extension is installed on this database. + * + * We must prevent slot creation before the BDR extension is created, + * otherwise the event trigger for DDL replication will record the + * extension's creation in bdr.bdr_queued_commands and the slot position + * will be before then, causing CREATE EXTENSION to be replayed. Since + * the other end already has the BDR extension (obviously) this will + * cause replay to fail. + * + * TODO: Should really test for the extension its self, but this is faster + * and easier... + */ + if (!IsTransactionState()) + { + tx_started = true; + StartTransactionCommand(); + } + +#ifdef BUILDING_BDR + /* + * If running BDR, we expect the remote end (us) to have the BDR extension + * installed before we permit slot creation. This prevents replication of + * the CREATE EXTENSION bdr; command its self. + */ + if (get_namespace_oid("bdr", true) == InvalidOid) + { + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("bdr extension does not exist on " BDR_LOCALID_FORMAT, + BDR_LOCALID_FORMAT_ARGS), + errdetail("Cannot create a BDR slot without the BDR extension installed"))); + } +#endif + /* no options are passed in during initialization, so don't complain there */ if (!is_init) { @@ -547,12 +583,6 @@ pg_decode_startup(LogicalDecodingContext * ctx, OutputPluginOptions *opt, bool i if (data->client_pg_version / 100 != PG_VERSION_NUM / 100) data->allow_sendrecv_protocol = false; - if (!IsTransactionState()) - { - tx_started = false; - StartTransactionCommand(); - } - bdr_maintain_schema(); data->bdr_schema_oid = get_namespace_oid("bdr", true); @@ -585,13 +615,14 @@ pg_decode_startup(LogicalDecodingContext * ctx, OutputPluginOptions *opt, bool i /* * Make sure it's safe to begin playing changes to the remote end. - * This'll ERROR out if we're not ready. + * This'll ERROR out if we're not ready. Note that this does NOT + * prevent slot creation, only START_REPLICATION from the slot. */ bdr_ensure_node_ready(); - - if (!tx_started) - CommitTransactionCommand(); } + + if (tx_started) + CommitTransactionCommand(); } /* diff --git a/expected/init.out b/expected/init.out index ab7045bd5d..4dd05289da 100644 --- a/expected/init.out +++ b/expected/init.out @@ -9,7 +9,7 @@ CREATE USER super SUPERUSER; GRANT ALL ON SCHEMA public TO nonsuper; \c regression GRANT ALL ON SCHEMA public TO nonsuper; -SELECT pg_sleep(5); +SELECT pg_sleep(10); pg_sleep ---------- diff --git a/sql/init.sql b/sql/init.sql index a614cb93cc..1027119873 100644 --- a/sql/init.sql +++ b/sql/init.sql @@ -12,7 +12,7 @@ GRANT ALL ON SCHEMA public TO nonsuper; \c regression GRANT ALL ON SCHEMA public TO nonsuper; -SELECT pg_sleep(5); +SELECT pg_sleep(10); -- emulate the pg_xlog_wait_remote_apply on vanilla postgres DO $DO$BEGIN