From 215cfa6a869957778b5c0b8a92b3d8a46ff76fb6 Mon Sep 17 00:00:00 2001 From: Craig Ringer Date: Wed, 1 Jul 2015 16:41:19 +0800 Subject: [PATCH] Permit DML on pg_catalog tables Because many pg_catalog tables don't have a PRIMARY KEY we were rejecting DML on them. Since pg_catalog writes don't get replicated anyway, it's safe to permit such writes. Fixes #102 --- bdr_executor.c | 13 +++++++++++++ expected/dml/missing_pk.out | 33 +++++++++++++++++++++++++++++++++ sql/dml/missing_pk.sql | 18 ++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/bdr_executor.c b/bdr_executor.c index 5eaae4bb8f..c5e196b5b9 100644 --- a/bdr_executor.c +++ b/bdr_executor.c @@ -25,6 +25,7 @@ #include "catalog/indexing.h" #include "catalog/namespace.h" +#include "catalog/pg_namespace.h" #include "catalog/pg_trigger.h" #include "commands/event_trigger.h" @@ -956,6 +957,18 @@ BdrExecutorStart(QueryDesc *queryDesc, int eflags) continue; } + /* + * Since changes to pg_catalog aren't replicated directly there's + * no strong need to suppress direct UPDATEs on them. The usual + * rule of "it's dumb to modify the catalogs directly if you don't + * know what you're doing" applies. + */ + if (RelationGetNamespace(rel) == PG_CATALOG_NAMESPACE) + { + RelationClose(rel); + continue; + } + if (read_only_node) ereport(ERROR, (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION), diff --git a/expected/dml/missing_pk.out b/expected/dml/missing_pk.out index 831f82e859..332698d80c 100644 --- a/expected/dml/missing_pk.out +++ b/expected/dml/missing_pk.out @@ -109,6 +109,39 @@ SELECT * FROM bdr_missing_pk; (0 rows) \c :writedb1 +-- Direct updates to the catalogs should be permitted, though +-- not necessarily smart. +UPDATE pg_class +SET relname = 'bdr_missing_pk_renamed' +WHERE relname = 'bdr_missing_pk'; +\dt bdr_missing_pk* + List of relations + Schema | Name | Type | Owner +--------+------------------------+-------+------- + public | bdr_missing_pk_parent | table | craig + public | bdr_missing_pk_renamed | table | craig +(2 rows) + +SELECT pg_xlog_wait_remote_apply(pg_current_xlog_location(), 0); + pg_xlog_wait_remote_apply +--------------------------- + +(1 row) + +\c :readdb2 +-- The catalog change should not replicate +\dt bdr_missing_pk* + List of relations + Schema | Name | Type | Owner +--------+-----------------------+-------+------- + public | bdr_missing_pk | table | craig + public | bdr_missing_pk_parent | table | craig +(2 rows) + +\c :writedb1 +UPDATE pg_class +SET relname = 'bdr_missing_pk' +WHERE relname = 'bdr_missing_pk_renamed'; BEGIN; SET LOCAL bdr.permit_ddl_locking = true; SELECT bdr.bdr_replicate_ddl_command($$DROP TABLE public.bdr_missing_pk CASCADE;$$); diff --git a/sql/dml/missing_pk.sql b/sql/dml/missing_pk.sql index 63df87683a..03a05ad62b 100644 --- a/sql/dml/missing_pk.sql +++ b/sql/dml/missing_pk.sql @@ -61,6 +61,24 @@ SELECT pg_xlog_wait_remote_apply(pg_current_xlog_location(), 0); SELECT * FROM bdr_missing_pk; \c :writedb1 +-- Direct updates to the catalogs should be permitted, though +-- not necessarily smart. +UPDATE pg_class +SET relname = 'bdr_missing_pk_renamed' +WHERE relname = 'bdr_missing_pk'; + +\dt bdr_missing_pk* +SELECT pg_xlog_wait_remote_apply(pg_current_xlog_location(), 0); + +\c :readdb2 +-- The catalog change should not replicate +\dt bdr_missing_pk* + +\c :writedb1 +UPDATE pg_class +SET relname = 'bdr_missing_pk' +WHERE relname = 'bdr_missing_pk_renamed'; + BEGIN; SET LOCAL bdr.permit_ddl_locking = true; SELECT bdr.bdr_replicate_ddl_command($$DROP TABLE public.bdr_missing_pk CASCADE;$$); -- 2.39.5