mirror of
https://github.com/postgres/postgres.git
synced 2025-07-11 10:01:57 +03:00
Apply table and domain CHECK constraints in name order.
Previously, CHECK constraints of the same scope were checked in whatever order they happened to be read from pg_constraint. (Usually, but not reliably, this would be creation order for domain constraints and reverse creation order for table constraints, because of differing implementation details.) Nondeterministic results of this sort are problematic at least for testing purposes, and in discussion it was agreed to be a violation of the principle of least astonishment. Therefore, borrow the principle already established for triggers, and apply such checks in name order (using strcmp() sort rules). This lets users control the check order if they have a mind to. Domain CHECK constraints still follow the rule of checking lower nested domains' constraints first; the name sort only applies to multiple constraints attached to the same domain. In passing, I failed to resist the temptation to wordsmith a bit in create_domain.sgml. Apply to HEAD only, since this could result in a behavioral change in existing applications, and the potential regression test failures have not actually been observed in our buildfarm.
This commit is contained in:
17
src/backend/utils/cache/relcache.c
vendored
17
src/backend/utils/cache/relcache.c
vendored
@ -271,6 +271,7 @@ static TupleDesc GetPgClassDescriptor(void);
|
||||
static TupleDesc GetPgIndexDescriptor(void);
|
||||
static void AttrDefaultFetch(Relation relation);
|
||||
static void CheckConstraintFetch(Relation relation);
|
||||
static int CheckConstraintCmp(const void *a, const void *b);
|
||||
static List *insert_ordered_oid(List *list, Oid datum);
|
||||
static void IndexSupportInitialize(oidvector *indclass,
|
||||
RegProcedure *indexSupport,
|
||||
@ -3734,6 +3735,22 @@ CheckConstraintFetch(Relation relation)
|
||||
if (found != ncheck)
|
||||
elog(ERROR, "%d constraint record(s) missing for rel %s",
|
||||
ncheck - found, RelationGetRelationName(relation));
|
||||
|
||||
/* Sort the records so that CHECKs are applied in a deterministic order */
|
||||
if (ncheck > 1)
|
||||
qsort(check, ncheck, sizeof(ConstrCheck), CheckConstraintCmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* qsort comparator to sort ConstrCheck entries by name
|
||||
*/
|
||||
static int
|
||||
CheckConstraintCmp(const void *a, const void *b)
|
||||
{
|
||||
const ConstrCheck *ca = (const ConstrCheck *) a;
|
||||
const ConstrCheck *cb = (const ConstrCheck *) b;
|
||||
|
||||
return strcmp(ca->ccname, cb->ccname);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user