diff options
Diffstat (limited to 'src/backend/commands/typecmds.c')
-rw-r--r-- | src/backend/commands/typecmds.c | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 29ac5d569d7..8e5134b2c35 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -1222,10 +1222,10 @@ DefineEnum(CreateEnumStmt *stmt) /* * AlterEnum - * Adds a new label to an existing enum. + * ALTER TYPE on an enum. */ ObjectAddress -AlterEnum(AlterEnumStmt *stmt) +AlterEnum(AlterEnumStmt *stmt, bool isTopLevel) { Oid enum_type_oid; TypeName *typename; @@ -1243,8 +1243,6 @@ AlterEnum(AlterEnumStmt *stmt) /* Check it's an enum and check user has permission to ALTER the enum */ checkEnumOwner(tup); - ReleaseSysCache(tup); - if (stmt->oldVal) { /* Rename an existing label */ @@ -1253,6 +1251,27 @@ AlterEnum(AlterEnumStmt *stmt) else { /* Add a new label */ + + /* + * Ordinarily we disallow adding values within transaction blocks, + * because we can't cope with enum OID values getting into indexes and + * then having their defining pg_enum entries go away. However, it's + * okay if the enum type was created in the current transaction, since + * then there can be no such indexes that wouldn't themselves go away + * on rollback. (We support this case because pg_dump + * --binary-upgrade needs it.) We test this by seeing if the pg_type + * row has xmin == current XID and is not HEAP_UPDATED. If it is + * HEAP_UPDATED, we can't be sure whether the type was created or only + * modified in this xact. So we are disallowing some cases that could + * theoretically be safe; but fortunately pg_dump only needs the + * simplest case. + */ + if (HeapTupleHeaderGetXmin(tup->t_data) == GetCurrentTransactionId() && + !(tup->t_data->t_infomask & HEAP_UPDATED)) + /* safe to do inside transaction block */ ; + else + PreventTransactionChain(isTopLevel, "ALTER TYPE ... ADD"); + AddEnumLabel(enum_type_oid, stmt->newVal, stmt->newValNeighbor, stmt->newValIsAfter, stmt->skipIfNewValExists); @@ -1262,6 +1281,8 @@ AlterEnum(AlterEnumStmt *stmt) ObjectAddressSet(address, TypeRelationId, enum_type_oid); + ReleaseSysCache(tup); + return address; } |