aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/typecmds.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/typecmds.c')
-rw-r--r--src/backend/commands/typecmds.c29
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;
}