mirror of
https://github.com/postgres/postgres.git
synced 2025-11-09 06:21:09 +03:00
Revert to 9.6 treatment of ALTER TYPE enumtype ADD VALUE.
This reverts commit15bc038f9, along with the followon commits1635e80d3and984c92074that tried to clean up the problems exposed by bug #14825. The result was incomplete because it failed to address parallel-query requirements. With 10.0 release so close upon us, now does not seem like the time to be adding more code to fix that. I hope we can un-revert this code and add the missing parallel query support during the v11 cycle. Back-patch to v10. Discussion: https://postgr.es/m/20170922185904.1448.16585@wrigleys.postgresql.org
This commit is contained in:
@@ -19,7 +19,6 @@
|
||||
#include "catalog/indexing.h"
|
||||
#include "catalog/pg_enum.h"
|
||||
#include "libpq/pqformat.h"
|
||||
#include "storage/procarray.h"
|
||||
#include "utils/array.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/fmgroids.h"
|
||||
@@ -32,79 +31,6 @@ static Oid enum_endpoint(Oid enumtypoid, ScanDirection direction);
|
||||
static ArrayType *enum_range_internal(Oid enumtypoid, Oid lower, Oid upper);
|
||||
|
||||
|
||||
/*
|
||||
* Disallow use of an uncommitted pg_enum tuple.
|
||||
*
|
||||
* We need to make sure that uncommitted enum values don't get into indexes.
|
||||
* If they did, and if we then rolled back the pg_enum addition, we'd have
|
||||
* broken the index because value comparisons will not work reliably without
|
||||
* an underlying pg_enum entry. (Note that removal of the heap entry
|
||||
* containing an enum value is not sufficient to ensure that it doesn't appear
|
||||
* in upper levels of indexes.) To do this we prevent an uncommitted row from
|
||||
* being used for any SQL-level purpose. This is stronger than necessary,
|
||||
* since the value might not be getting inserted into a table or there might
|
||||
* be no index on its column, but it's easy to enforce centrally.
|
||||
*
|
||||
* However, it's okay to allow use of uncommitted values belonging to enum
|
||||
* types that were themselves created in the same transaction, because then
|
||||
* any such index would also be new and would go away altogether on rollback.
|
||||
* We don't implement that fully right now, but we do allow free use of enum
|
||||
* values created during CREATE TYPE AS ENUM, which are surely of the same
|
||||
* lifespan as the enum type. (This case is required by "pg_restore -1".)
|
||||
* Values added by ALTER TYPE ADD VALUE are currently restricted, but could
|
||||
* be allowed if the enum type could be proven to have been created earlier
|
||||
* in the same transaction. (Note that comparing tuple xmins would not work
|
||||
* for that, because the type tuple might have been updated in the current
|
||||
* transaction. Subtransactions also create hazards to be accounted for.)
|
||||
*
|
||||
* This function needs to be called (directly or indirectly) in any of the
|
||||
* functions below that could return an enum value to SQL operations.
|
||||
*/
|
||||
static void
|
||||
check_safe_enum_use(HeapTuple enumval_tup)
|
||||
{
|
||||
TransactionId xmin;
|
||||
Form_pg_enum en;
|
||||
|
||||
/*
|
||||
* If the row is hinted as committed, it's surely safe. This provides a
|
||||
* fast path for all normal use-cases.
|
||||
*/
|
||||
if (HeapTupleHeaderXminCommitted(enumval_tup->t_data))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Usually, a row would get hinted as committed when it's read or loaded
|
||||
* into syscache; but just in case not, let's check the xmin directly.
|
||||
*/
|
||||
xmin = HeapTupleHeaderGetXmin(enumval_tup->t_data);
|
||||
if (!TransactionIdIsInProgress(xmin) &&
|
||||
TransactionIdDidCommit(xmin))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Check if the enum value is blacklisted. If not, it's safe, because it
|
||||
* was made during CREATE TYPE AS ENUM and can't be shorter-lived than its
|
||||
* owning type. (This'd also be false for values made by other
|
||||
* transactions; but the previous tests should have handled all of those.)
|
||||
*/
|
||||
if (!EnumBlacklisted(HeapTupleGetOid(enumval_tup)))
|
||||
return;
|
||||
|
||||
/*
|
||||
* There might well be other tests we could do here to narrow down the
|
||||
* unsafe conditions, but for now just raise an exception.
|
||||
*/
|
||||
en = (Form_pg_enum) GETSTRUCT(enumval_tup);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNSAFE_NEW_ENUM_VALUE_USAGE),
|
||||
errmsg("unsafe use of new value \"%s\" of enum type %s",
|
||||
NameStr(en->enumlabel),
|
||||
format_type_be(en->enumtypid)),
|
||||
errhint("New enum values must be committed before they can be used.")));
|
||||
}
|
||||
|
||||
|
||||
/* Basic I/O support */
|
||||
|
||||
Datum
|
||||
@@ -133,9 +59,6 @@ enum_in(PG_FUNCTION_ARGS)
|
||||
format_type_be(enumtypoid),
|
||||
name)));
|
||||
|
||||
/* check it's safe to use in SQL */
|
||||
check_safe_enum_use(tup);
|
||||
|
||||
/*
|
||||
* This comes from pg_enum.oid and stores system oids in user tables. This
|
||||
* oid must be preserved by binary upgrades.
|
||||
@@ -201,9 +124,6 @@ enum_recv(PG_FUNCTION_ARGS)
|
||||
format_type_be(enumtypoid),
|
||||
name)));
|
||||
|
||||
/* check it's safe to use in SQL */
|
||||
check_safe_enum_use(tup);
|
||||
|
||||
enumoid = HeapTupleGetOid(tup);
|
||||
|
||||
ReleaseSysCache(tup);
|
||||
@@ -411,16 +331,9 @@ enum_endpoint(Oid enumtypoid, ScanDirection direction)
|
||||
|
||||
enum_tuple = systable_getnext_ordered(enum_scan, direction);
|
||||
if (HeapTupleIsValid(enum_tuple))
|
||||
{
|
||||
/* check it's safe to use in SQL */
|
||||
check_safe_enum_use(enum_tuple);
|
||||
minmax = HeapTupleGetOid(enum_tuple);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* should only happen with an empty enum */
|
||||
minmax = InvalidOid;
|
||||
}
|
||||
|
||||
systable_endscan_ordered(enum_scan);
|
||||
index_close(enum_idx, AccessShareLock);
|
||||
@@ -581,9 +494,6 @@ enum_range_internal(Oid enumtypoid, Oid lower, Oid upper)
|
||||
|
||||
if (left_found)
|
||||
{
|
||||
/* check it's safe to use in SQL */
|
||||
check_safe_enum_use(enum_tuple);
|
||||
|
||||
if (cnt >= max)
|
||||
{
|
||||
max *= 2;
|
||||
|
||||
Reference in New Issue
Block a user