From 97a528f04792e5a0dccf77d927db5ae1b37c378d Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Wed, 3 Oct 2018 14:09:59 +1300 Subject: [PATCH 2/2] fixup! Relax transactional restrictions on ALTER TYPE ... ADD VALUE (redux). --- src/backend/access/transam/parallel.c | 20 +++++++++- src/backend/catalog/pg_enum.c | 53 +++++++++++++++++++++++++++ src/include/catalog/pg_enum.h | 3 ++ 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/src/backend/access/transam/parallel.c b/src/backend/access/transam/parallel.c index cdaa32e29a4..17948818871 100644 --- a/src/backend/access/transam/parallel.c +++ b/src/backend/access/transam/parallel.c @@ -19,6 +19,7 @@ #include "access/session.h" #include "access/xact.h" #include "access/xlog.h" +#include "catalog/pg_enum.h" #include "catalog/index.h" #include "catalog/namespace.h" #include "commands/async.h" @@ -71,6 +72,7 @@ #define PARALLEL_KEY_SESSION_DSM UINT64CONST(0xFFFFFFFFFFFF000A) #define PARALLEL_KEY_REINDEX_STATE UINT64CONST(0xFFFFFFFFFFFF000B) #define PARALLEL_KEY_RELMAPPER_STATE UINT64CONST(0xFFFFFFFFFFFF000C) +#define PARALLEL_KEY_ENUMBLACKLIST UINT64CONST(0xFFFFFFFFFFFF000D) /* Fixed-size parallel state. */ typedef struct FixedParallelState @@ -208,6 +210,7 @@ InitializeParallelDSM(ParallelContext *pcxt) Size tstatelen = 0; Size reindexlen = 0; Size relmapperlen = 0; + Size enumblacklistlen = 0; Size segsize = 0; int i; FixedParallelState *fps; @@ -261,8 +264,10 @@ InitializeParallelDSM(ParallelContext *pcxt) shm_toc_estimate_chunk(&pcxt->estimator, reindexlen); relmapperlen = EstimateRelationMapSpace(); shm_toc_estimate_chunk(&pcxt->estimator, relmapperlen); + enumblacklistlen = EstimateEnumBlacklistSpace(); + shm_toc_estimate_chunk(&pcxt->estimator, enumblacklistlen); /* If you add more chunks here, you probably need to add keys. */ - shm_toc_estimate_keys(&pcxt->estimator, 9); + shm_toc_estimate_keys(&pcxt->estimator, 10); /* Estimate space need for error queues. */ StaticAssertStmt(BUFFERALIGN(PARALLEL_ERROR_QUEUE_SIZE) == @@ -336,6 +341,7 @@ InitializeParallelDSM(ParallelContext *pcxt) char *error_queue_space; char *session_dsm_handle_space; char *entrypointstate; + char *enumblacklistspace; Size lnamelen; /* Serialize shared libraries we have loaded. */ @@ -385,6 +391,12 @@ InitializeParallelDSM(ParallelContext *pcxt) shm_toc_insert(pcxt->toc, PARALLEL_KEY_RELMAPPER_STATE, relmapperspace); + /* Serialize enum blacklist state. */ + enumblacklistspace = shm_toc_allocate(pcxt->toc, enumblacklistlen); + SerializeEnumBlacklist(enumblacklistspace); + shm_toc_insert(pcxt->toc, PARALLEL_KEY_ENUMBLACKLIST, + enumblacklistspace); + /* Allocate space for worker information. */ pcxt->worker = palloc0(sizeof(ParallelWorkerInfo) * pcxt->nworkers); @@ -1218,6 +1230,7 @@ ParallelWorkerMain(Datum main_arg) char *tstatespace; char *reindexspace; char *relmapperspace; + char *enumblacklistspace; StringInfoData msgbuf; char *session_dsm_handle_space; @@ -1397,6 +1410,11 @@ ParallelWorkerMain(Datum main_arg) relmapperspace = shm_toc_lookup(toc, PARALLEL_KEY_RELMAPPER_STATE, false); RestoreRelationMap(relmapperspace); + /* Restore enum blacklist. */ + enumblacklistspace = shm_toc_lookup(toc, PARALLEL_KEY_ENUMBLACKLIST, + false); + RestoreEnumBlacklist(enumblacklistspace); + /* * We've initialized all of our state now; nothing should change * hereafter. diff --git a/src/backend/catalog/pg_enum.c b/src/backend/catalog/pg_enum.c index 297d64a8106..bb4090c60c8 100644 --- a/src/backend/catalog/pg_enum.c +++ b/src/backend/catalog/pg_enum.c @@ -684,3 +684,56 @@ sort_order_cmp(const void *p1, const void *p2) else return 0; } + +Size +EstimateEnumBlacklistSpace(void) +{ + if (!enum_blacklist) + return sizeof(Oid); + return sizeof(Oid) + sizeof(Oid) * hash_get_num_entries(enum_blacklist); +} + +void +SerializeEnumBlacklist(void *space) +{ + Oid *serialized = (Oid *) space; + HASH_SEQ_STATUS status; + Oid *value; + + if (!enum_blacklist) + { + *serialized = 0; + return; + } + + *serialized++ = hash_get_num_entries(enum_blacklist); + hash_seq_init(&status, enum_blacklist); + while ((value = (Oid *) hash_seq_search(&status))) + *serialized++ = *value; +} + +void +RestoreEnumBlacklist(void *space) +{ + Oid *serialized = (Oid *) space; + HASHCTL hash_ctl; + int num_elements; + + Assert(!enum_blacklist); + + num_elements = *serialized++; + if (num_elements == 0) + return; + + memset(&hash_ctl, 0, sizeof(hash_ctl)); + hash_ctl.keysize = sizeof(Oid); + hash_ctl.entrysize = sizeof(Oid); + hash_ctl.hcxt = TopTransactionContext; + enum_blacklist = hash_create("Enum value blacklist", + 32, + &hash_ctl, + HASH_ELEM | HASH_BLOBS | HASH_CONTEXT); + + while (num_elements-- > 0) + hash_search(enum_blacklist, serialized++, HASH_ENTER, NULL); +} diff --git a/src/include/catalog/pg_enum.h b/src/include/catalog/pg_enum.h index a70a05cc64c..2f92d8a41e9 100644 --- a/src/include/catalog/pg_enum.h +++ b/src/include/catalog/pg_enum.h @@ -53,6 +53,9 @@ extern void AddEnumLabel(Oid enumTypeOid, const char *newVal, extern void RenameEnumLabel(Oid enumTypeOid, const char *oldVal, const char *newVal); extern bool EnumBlacklisted(Oid enum_id); +extern Size EstimateEnumBlacklistSpace(void); +extern void SerializeEnumBlacklist(void *space); +extern void RestoreEnumBlacklist(void *space); extern void AtEOXact_Enum(void); #endif /* PG_ENUM_H */ -- 2.17.1 (Apple Git-112)