0001-enforce-constraint-name-uniqueness.patch
text/x-diff
Filename: 0001-enforce-constraint-name-uniqueness.patch
Type: text/x-diff
Part: 0
Patch
Format: unified
Series: patch 0001
| File | + | − |
|---|---|---|
| src/backend/catalog/pg_constraint.c | 0 | 0 |
| src/backend/commands/tablecmds.c | 0 | 0 |
| src/backend/commands/typecmds.c | 0 | 0 |
| src/backend/utils/cache/relcache.c | 0 | 0 |
| src/include/catalog/indexing.h | 0 | 0 |
| src/include/catalog/pg_constraint.h | 0 | 0 |
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
index 7a6d158..3d65464 100644
*** a/src/backend/catalog/pg_constraint.c
--- b/src/backend/catalog/pg_constraint.c
*************** CloneForeignKeyConstraints(Oid parentId,
*** 443,449 ****
ScanKeyInit(&key,
Anum_pg_constraint_conrelid, BTEqualStrategyNumber,
F_OIDEQ, ObjectIdGetDatum(parentId));
! scan = systable_beginscan(pg_constraint, ConstraintRelidIndexId, true,
NULL, 1, &key);
while ((tuple = systable_getnext(scan)) != NULL)
--- 443,449 ----
ScanKeyInit(&key,
Anum_pg_constraint_conrelid, BTEqualStrategyNumber,
F_OIDEQ, ObjectIdGetDatum(parentId));
! scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
NULL, 1, &key);
while ((tuple = systable_getnext(scan)) != NULL)
*************** AlterConstraintNamespaces(Oid ownerId, O
*** 944,975 ****
Oid newNspId, bool isType, ObjectAddresses *objsMoved)
{
Relation conRel;
! ScanKeyData key[1];
SysScanDesc scan;
HeapTuple tup;
conRel = heap_open(ConstraintRelationId, RowExclusiveLock);
! if (isType)
! {
! ScanKeyInit(&key[0],
! Anum_pg_constraint_contypid,
! BTEqualStrategyNumber, F_OIDEQ,
! ObjectIdGetDatum(ownerId));
!
! scan = systable_beginscan(conRel, ConstraintTypidIndexId, true,
! NULL, 1, key);
! }
! else
! {
! ScanKeyInit(&key[0],
! Anum_pg_constraint_conrelid,
! BTEqualStrategyNumber, F_OIDEQ,
! ObjectIdGetDatum(ownerId));
! scan = systable_beginscan(conRel, ConstraintRelidIndexId, true,
! NULL, 1, key);
! }
while (HeapTupleIsValid((tup = systable_getnext(scan))))
{
--- 944,966 ----
Oid newNspId, bool isType, ObjectAddresses *objsMoved)
{
Relation conRel;
! ScanKeyData key[2];
SysScanDesc scan;
HeapTuple tup;
conRel = heap_open(ConstraintRelationId, RowExclusiveLock);
! ScanKeyInit(&key[0],
! Anum_pg_constraint_conrelid,
! BTEqualStrategyNumber, F_OIDEQ,
! ObjectIdGetDatum(isType ? InvalidOid : ownerId));
! ScanKeyInit(&key[1],
! Anum_pg_constraint_contypid,
! BTEqualStrategyNumber, F_OIDEQ,
! ObjectIdGetDatum(isType ? ownerId : InvalidOid));
! scan = systable_beginscan(conRel, ConstraintRelidTypidNameIndexId, true,
! NULL, 2, key);
while (HeapTupleIsValid((tup = systable_getnext(scan))))
{
*************** get_relation_constraint_oid(Oid relid, c
*** 1059,1095 ****
Relation pg_constraint;
HeapTuple tuple;
SysScanDesc scan;
! ScanKeyData skey[1];
Oid conOid = InvalidOid;
- /*
- * Fetch the constraint tuple from pg_constraint. There may be more than
- * one match, because constraints are not required to have unique names;
- * if so, error out.
- */
pg_constraint = heap_open(ConstraintRelationId, AccessShareLock);
ScanKeyInit(&skey[0],
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(relid));
! scan = systable_beginscan(pg_constraint, ConstraintRelidIndexId, true,
! NULL, 1, skey);
! while (HeapTupleIsValid(tuple = systable_getnext(scan)))
{
! Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
!
! if (strcmp(NameStr(con->conname), conname) == 0)
! {
! if (OidIsValid(conOid))
! ereport(ERROR,
! (errcode(ERRCODE_DUPLICATE_OBJECT),
! errmsg("table \"%s\" has multiple constraints named \"%s\"",
! get_rel_name(relid), conname)));
! conOid = HeapTupleGetOid(tuple);
! }
}
systable_endscan(scan);
--- 1050,1080 ----
Relation pg_constraint;
HeapTuple tuple;
SysScanDesc scan;
! ScanKeyData skey[3];
Oid conOid = InvalidOid;
pg_constraint = heap_open(ConstraintRelationId, AccessShareLock);
ScanKeyInit(&skey[0],
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(relid));
+ ScanKeyInit(&skey[1],
+ Anum_pg_constraint_contypid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(InvalidOid));
+ ScanKeyInit(&skey[2],
+ Anum_pg_constraint_conname,
+ BTEqualStrategyNumber, F_NAMEEQ,
+ CStringGetDatum(conname));
! scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
! NULL, 3, skey);
! /* There can be at most one matching row */
! if (HeapTupleIsValid(tuple = systable_getnext(scan)))
{
! conOid = HeapTupleGetOid(tuple);
}
systable_endscan(scan);
*************** get_relation_constraint_attnos(Oid relid
*** 1126,1192 ****
Relation pg_constraint;
HeapTuple tuple;
SysScanDesc scan;
! ScanKeyData skey[1];
/* Set *constraintOid, to avoid complaints about uninitialized vars */
*constraintOid = InvalidOid;
- /*
- * Fetch the constraint tuple from pg_constraint. There may be more than
- * one match, because constraints are not required to have unique names;
- * if so, error out.
- */
pg_constraint = heap_open(ConstraintRelationId, AccessShareLock);
ScanKeyInit(&skey[0],
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(relid));
! scan = systable_beginscan(pg_constraint, ConstraintRelidIndexId, true,
! NULL, 1, skey);
! while (HeapTupleIsValid(tuple = systable_getnext(scan)))
{
- Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
Datum adatum;
bool isNull;
- ArrayType *arr;
- int16 *attnums;
- int numcols;
- int i;
-
- /* Check the constraint name */
- if (strcmp(NameStr(con->conname), conname) != 0)
- continue;
- if (OidIsValid(*constraintOid))
- ereport(ERROR,
- (errcode(ERRCODE_DUPLICATE_OBJECT),
- errmsg("table \"%s\" has multiple constraints named \"%s\"",
- get_rel_name(relid), conname)));
*constraintOid = HeapTupleGetOid(tuple);
/* Extract the conkey array, ie, attnums of constrained columns */
adatum = heap_getattr(tuple, Anum_pg_constraint_conkey,
RelationGetDescr(pg_constraint), &isNull);
! if (isNull)
! continue; /* no constrained columns */
! arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
! numcols = ARR_DIMS(arr)[0];
! if (ARR_NDIM(arr) != 1 ||
! numcols < 0 ||
! ARR_HASNULL(arr) ||
! ARR_ELEMTYPE(arr) != INT2OID)
! elog(ERROR, "conkey is not a 1-D smallint array");
! attnums = (int16 *) ARR_DATA_PTR(arr);
! /* Construct the result value */
! for (i = 0; i < numcols; i++)
! {
! conattnos = bms_add_member(conattnos,
! attnums[i] - FirstLowInvalidHeapAttributeNumber);
}
}
--- 1111,1172 ----
Relation pg_constraint;
HeapTuple tuple;
SysScanDesc scan;
! ScanKeyData skey[3];
/* Set *constraintOid, to avoid complaints about uninitialized vars */
*constraintOid = InvalidOid;
pg_constraint = heap_open(ConstraintRelationId, AccessShareLock);
ScanKeyInit(&skey[0],
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(relid));
+ ScanKeyInit(&skey[1],
+ Anum_pg_constraint_contypid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(InvalidOid));
+ ScanKeyInit(&skey[2],
+ Anum_pg_constraint_conname,
+ BTEqualStrategyNumber, F_NAMEEQ,
+ CStringGetDatum(conname));
! scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
! NULL, 3, skey);
! /* There can be at most one matching row */
! if (HeapTupleIsValid(tuple = systable_getnext(scan)))
{
Datum adatum;
bool isNull;
*constraintOid = HeapTupleGetOid(tuple);
/* Extract the conkey array, ie, attnums of constrained columns */
adatum = heap_getattr(tuple, Anum_pg_constraint_conkey,
RelationGetDescr(pg_constraint), &isNull);
! if (!isNull)
! {
! ArrayType *arr;
! int numcols;
! int16 *attnums;
! int i;
! arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
! numcols = ARR_DIMS(arr)[0];
! if (ARR_NDIM(arr) != 1 ||
! numcols < 0 ||
! ARR_HASNULL(arr) ||
! ARR_ELEMTYPE(arr) != INT2OID)
! elog(ERROR, "conkey is not a 1-D smallint array");
! attnums = (int16 *) ARR_DATA_PTR(arr);
! /* Construct the result value */
! for (i = 0; i < numcols; i++)
! {
! conattnos = bms_add_member(conattnos,
! attnums[i] - FirstLowInvalidHeapAttributeNumber);
! }
}
}
*************** get_relation_idx_constraint_oid(Oid rela
*** 1224,1230 ****
BTEqualStrategyNumber,
F_OIDEQ,
ObjectIdGetDatum(relationId));
! scan = systable_beginscan(pg_constraint, ConstraintRelidIndexId,
true, NULL, 1, &key);
while ((tuple = systable_getnext(scan)) != NULL)
{
--- 1204,1210 ----
BTEqualStrategyNumber,
F_OIDEQ,
ObjectIdGetDatum(relationId));
! scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId,
true, NULL, 1, &key);
while ((tuple = systable_getnext(scan)) != NULL)
{
*************** get_domain_constraint_oid(Oid typid, con
*** 1254,1291 ****
Relation pg_constraint;
HeapTuple tuple;
SysScanDesc scan;
! ScanKeyData skey[1];
Oid conOid = InvalidOid;
- /*
- * Fetch the constraint tuple from pg_constraint. There may be more than
- * one match, because constraints are not required to have unique names;
- * if so, error out.
- */
pg_constraint = heap_open(ConstraintRelationId, AccessShareLock);
ScanKeyInit(&skey[0],
Anum_pg_constraint_contypid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(typid));
! scan = systable_beginscan(pg_constraint, ConstraintTypidIndexId, true,
! NULL, 1, skey);
!
! while (HeapTupleIsValid(tuple = systable_getnext(scan)))
! {
! Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
! if (strcmp(NameStr(con->conname), conname) == 0)
! {
! if (OidIsValid(conOid))
! ereport(ERROR,
! (errcode(ERRCODE_DUPLICATE_OBJECT),
! errmsg("domain %s has multiple constraints named \"%s\"",
! format_type_be(typid), conname)));
! conOid = HeapTupleGetOid(tuple);
! }
! }
systable_endscan(scan);
--- 1234,1263 ----
Relation pg_constraint;
HeapTuple tuple;
SysScanDesc scan;
! ScanKeyData skey[3];
Oid conOid = InvalidOid;
pg_constraint = heap_open(ConstraintRelationId, AccessShareLock);
ScanKeyInit(&skey[0],
+ Anum_pg_constraint_conrelid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(InvalidOid));
+ ScanKeyInit(&skey[1],
Anum_pg_constraint_contypid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(typid));
+ ScanKeyInit(&skey[2],
+ Anum_pg_constraint_conname,
+ BTEqualStrategyNumber, F_NAMEEQ,
+ CStringGetDatum(conname));
! scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
! NULL, 3, skey);
! /* There can be at most one matching row */
! if (HeapTupleIsValid(tuple = systable_getnext(scan)))
! conOid = HeapTupleGetOid(tuple);
systable_endscan(scan);
*************** get_primary_key_attnos(Oid relid, bool d
*** 1335,1341 ****
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(relid));
! scan = systable_beginscan(pg_constraint, ConstraintRelidIndexId, true,
NULL, 1, skey);
while (HeapTupleIsValid(tuple = systable_getnext(scan)))
--- 1307,1313 ----
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(relid));
! scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
NULL, 1, skey);
while (HeapTupleIsValid(tuple = systable_getnext(scan)))
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index f46af41..a3edef5 100644
*** a/src/backend/commands/tablecmds.c
--- b/src/backend/commands/tablecmds.c
*************** ATExecAlterConstraint(Relation rel, Alte
*** 7801,7810 ****
Constraint *cmdcon;
Relation conrel;
SysScanDesc scan;
! ScanKeyData key;
HeapTuple contuple;
! Form_pg_constraint currcon = NULL;
! bool found = false;
ObjectAddress address;
cmdcon = castNode(Constraint, cmd->def);
--- 7801,7809 ----
Constraint *cmdcon;
Relation conrel;
SysScanDesc scan;
! ScanKeyData skey[3];
HeapTuple contuple;
! Form_pg_constraint currcon;
ObjectAddress address;
cmdcon = castNode(Constraint, cmd->def);
*************** ATExecAlterConstraint(Relation rel, Alte
*** 7814,7842 ****
/*
* Find and check the target constraint
*/
! ScanKeyInit(&key,
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(rel)));
! scan = systable_beginscan(conrel, ConstraintRelidIndexId,
! true, NULL, 1, &key);
!
! while (HeapTupleIsValid(contuple = systable_getnext(scan)))
! {
! currcon = (Form_pg_constraint) GETSTRUCT(contuple);
! if (strcmp(NameStr(currcon->conname), cmdcon->conname) == 0)
! {
! found = true;
! break;
! }
! }
! if (!found)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("constraint \"%s\" of relation \"%s\" does not exist",
cmdcon->conname, RelationGetRelationName(rel))));
if (currcon->contype != CONSTRAINT_FOREIGN)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
--- 7813,7841 ----
/*
* Find and check the target constraint
*/
! ScanKeyInit(&skey[0],
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(rel)));
! ScanKeyInit(&skey[1],
! Anum_pg_constraint_contypid,
! BTEqualStrategyNumber, F_OIDEQ,
! ObjectIdGetDatum(InvalidOid));
! ScanKeyInit(&skey[2],
! Anum_pg_constraint_conname,
! BTEqualStrategyNumber, F_NAMEEQ,
! CStringGetDatum(cmdcon->conname));
! scan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId,
! true, NULL, 3, skey);
! /* There can be at most one matching row */
! if (!HeapTupleIsValid(contuple = systable_getnext(scan)))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("constraint \"%s\" of relation \"%s\" does not exist",
cmdcon->conname, RelationGetRelationName(rel))));
+ currcon = (Form_pg_constraint) GETSTRUCT(contuple);
if (currcon->contype != CONSTRAINT_FOREIGN)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
*************** ATExecValidateConstraint(Relation rel, c
*** 7969,7978 ****
{
Relation conrel;
SysScanDesc scan;
! ScanKeyData key;
HeapTuple tuple;
! Form_pg_constraint con = NULL;
! bool found = false;
ObjectAddress address;
conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
--- 7968,7976 ----
{
Relation conrel;
SysScanDesc scan;
! ScanKeyData skey[3];
HeapTuple tuple;
! Form_pg_constraint con;
ObjectAddress address;
conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
*************** ATExecValidateConstraint(Relation rel, c
*** 7980,8008 ****
/*
* Find and check the target constraint
*/
! ScanKeyInit(&key,
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(rel)));
! scan = systable_beginscan(conrel, ConstraintRelidIndexId,
! true, NULL, 1, &key);
!
! while (HeapTupleIsValid(tuple = systable_getnext(scan)))
! {
! con = (Form_pg_constraint) GETSTRUCT(tuple);
! if (strcmp(NameStr(con->conname), constrName) == 0)
! {
! found = true;
! break;
! }
! }
! if (!found)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("constraint \"%s\" of relation \"%s\" does not exist",
constrName, RelationGetRelationName(rel))));
if (con->contype != CONSTRAINT_FOREIGN &&
con->contype != CONSTRAINT_CHECK)
ereport(ERROR,
--- 7978,8006 ----
/*
* Find and check the target constraint
*/
! ScanKeyInit(&skey[0],
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(rel)));
! ScanKeyInit(&skey[1],
! Anum_pg_constraint_contypid,
! BTEqualStrategyNumber, F_OIDEQ,
! ObjectIdGetDatum(InvalidOid));
! ScanKeyInit(&skey[2],
! Anum_pg_constraint_conname,
! BTEqualStrategyNumber, F_NAMEEQ,
! CStringGetDatum(constrName));
! scan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId,
! true, NULL, 3, skey);
! /* There can be at most one matching row */
! if (!HeapTupleIsValid(tuple = systable_getnext(scan)))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("constraint \"%s\" of relation \"%s\" does not exist",
constrName, RelationGetRelationName(rel))));
+ con = (Form_pg_constraint) GETSTRUCT(tuple);
if (con->contype != CONSTRAINT_FOREIGN &&
con->contype != CONSTRAINT_CHECK)
ereport(ERROR,
*************** ATExecDropConstraint(Relation rel, const
*** 8865,8871 ****
Relation conrel;
Form_pg_constraint con;
SysScanDesc scan;
! ScanKeyData key;
HeapTuple tuple;
bool found = false;
bool is_no_inherit_constraint = false;
--- 8863,8869 ----
Relation conrel;
Form_pg_constraint con;
SysScanDesc scan;
! ScanKeyData skey[3];
HeapTuple tuple;
bool found = false;
bool is_no_inherit_constraint = false;
*************** ATExecDropConstraint(Relation rel, const
*** 8879,8900 ****
/*
* Find and drop the target constraint
*/
! ScanKeyInit(&key,
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(rel)));
! scan = systable_beginscan(conrel, ConstraintRelidIndexId,
! true, NULL, 1, &key);
! while (HeapTupleIsValid(tuple = systable_getnext(scan)))
{
ObjectAddress conobj;
con = (Form_pg_constraint) GETSTRUCT(tuple);
- if (strcmp(NameStr(con->conname), constrName) != 0)
- continue;
-
/* Don't drop inherited constraints */
if (con->coninhcount > 0 && !recursing)
ereport(ERROR,
--- 8877,8904 ----
/*
* Find and drop the target constraint
*/
! ScanKeyInit(&skey[0],
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(rel)));
! ScanKeyInit(&skey[1],
! Anum_pg_constraint_contypid,
! BTEqualStrategyNumber, F_OIDEQ,
! ObjectIdGetDatum(InvalidOid));
! ScanKeyInit(&skey[2],
! Anum_pg_constraint_conname,
! BTEqualStrategyNumber, F_NAMEEQ,
! CStringGetDatum(constrName));
! scan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId,
! true, NULL, 3, skey);
! /* There can be at most one matching row */
! if (HeapTupleIsValid(tuple = systable_getnext(scan)))
{
ObjectAddress conobj;
con = (Form_pg_constraint) GETSTRUCT(tuple);
/* Don't drop inherited constraints */
if (con->coninhcount > 0 && !recursing)
ereport(ERROR,
*************** ATExecDropConstraint(Relation rel, const
*** 8932,8940 ****
performDeletion(&conobj, behavior, 0);
found = true;
-
- /* constraint found and dropped -- no need to keep looping */
- break;
}
systable_endscan(scan);
--- 8936,8941 ----
*************** ATExecDropConstraint(Relation rel, const
*** 8990,9016 ****
childrel = heap_open(childrelid, NoLock);
CheckTableNotInUse(childrel, "ALTER TABLE");
! ScanKeyInit(&key,
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(childrelid));
! scan = systable_beginscan(conrel, ConstraintRelidIndexId,
! true, NULL, 1, &key);
!
! /* scan for matching tuple - there should only be one */
! while (HeapTupleIsValid(tuple = systable_getnext(scan)))
! {
! con = (Form_pg_constraint) GETSTRUCT(tuple);
!
! /* Right now only CHECK constraints can be inherited */
! if (con->contype != CONSTRAINT_CHECK)
! continue;
!
! if (strcmp(NameStr(con->conname), constrName) == 0)
! break;
! }
! if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("constraint \"%s\" of relation \"%s\" does not exist",
--- 8991,9013 ----
childrel = heap_open(childrelid, NoLock);
CheckTableNotInUse(childrel, "ALTER TABLE");
! ScanKeyInit(&skey[0],
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(childrelid));
! ScanKeyInit(&skey[1],
! Anum_pg_constraint_contypid,
! BTEqualStrategyNumber, F_OIDEQ,
! ObjectIdGetDatum(InvalidOid));
! ScanKeyInit(&skey[2],
! Anum_pg_constraint_conname,
! BTEqualStrategyNumber, F_NAMEEQ,
! CStringGetDatum(constrName));
! scan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId,
! true, NULL, 3, skey);
! /* There can be at most one matching row */
! if (!HeapTupleIsValid(tuple = systable_getnext(scan)))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("constraint \"%s\" of relation \"%s\" does not exist",
*************** ATExecDropConstraint(Relation rel, const
*** 9023,9028 ****
--- 9020,9029 ----
con = (Form_pg_constraint) GETSTRUCT(copy_tuple);
+ /* Right now only CHECK constraints can be inherited */
+ if (con->contype != CONSTRAINT_CHECK)
+ elog(ERROR, "inherited constraint is not a CHECK constraint");
+
if (con->coninhcount <= 0) /* shouldn't happen */
elog(ERROR, "relation %u has non-inherited constraint \"%s\"",
childrelid, constrName);
*************** MergeConstraintsIntoExisting(Relation ch
*** 11824,11830 ****
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(parent_rel)));
! parent_scan = systable_beginscan(catalog_relation, ConstraintRelidIndexId,
true, NULL, 1, &parent_key);
while (HeapTupleIsValid(parent_tuple = systable_getnext(parent_scan)))
--- 11825,11831 ----
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(parent_rel)));
! parent_scan = systable_beginscan(catalog_relation, ConstraintRelidTypidNameIndexId,
true, NULL, 1, &parent_key);
while (HeapTupleIsValid(parent_tuple = systable_getnext(parent_scan)))
*************** MergeConstraintsIntoExisting(Relation ch
*** 11847,11853 ****
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(child_rel)));
! child_scan = systable_beginscan(catalog_relation, ConstraintRelidIndexId,
true, NULL, 1, &child_key);
while (HeapTupleIsValid(child_tuple = systable_getnext(child_scan)))
--- 11848,11854 ----
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(child_rel)));
! child_scan = systable_beginscan(catalog_relation, ConstraintRelidTypidNameIndexId,
true, NULL, 1, &child_key);
while (HeapTupleIsValid(child_tuple = systable_getnext(child_scan)))
*************** RemoveInheritance(Relation child_rel, Re
*** 12068,12074 ****
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(parent_rel)));
! scan = systable_beginscan(catalogRelation, ConstraintRelidIndexId,
true, NULL, 1, key);
connames = NIL;
--- 12069,12075 ----
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(parent_rel)));
! scan = systable_beginscan(catalogRelation, ConstraintRelidTypidNameIndexId,
true, NULL, 1, key);
connames = NIL;
*************** RemoveInheritance(Relation child_rel, Re
*** 12088,12094 ****
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(child_rel)));
! scan = systable_beginscan(catalogRelation, ConstraintRelidIndexId,
true, NULL, 1, key);
while (HeapTupleIsValid(constraintTuple = systable_getnext(scan)))
--- 12089,12095 ----
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(child_rel)));
! scan = systable_beginscan(catalogRelation, ConstraintRelidTypidNameIndexId,
true, NULL, 1, key);
while (HeapTupleIsValid(constraintTuple = systable_getnext(scan)))
*************** ATPrepChangePersistence(Relation rel, bo
*** 12829,12835 ****
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(rel)));
scan = systable_beginscan(pg_constraint,
! toLogged ? ConstraintRelidIndexId : InvalidOid,
true, NULL, 1, skey);
while (HeapTupleIsValid(tuple = systable_getnext(scan)))
--- 12830,12836 ----
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(rel)));
scan = systable_beginscan(pg_constraint,
! toLogged ? ConstraintRelidTypidNameIndexId : InvalidOid,
true, NULL, 1, skey);
while (HeapTupleIsValid(tuple = systable_getnext(scan)))
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 175ecc8..a67f9ce 100644
*** a/src/backend/commands/typecmds.c
--- b/src/backend/commands/typecmds.c
*************** AlterDomainNotNull(List *names, bool not
*** 2444,2449 ****
--- 2444,2451 ----
* AlterDomainDropConstraint
*
* Implements the ALTER DOMAIN DROP CONSTRAINT statement
+ *
+ * Returns ObjectAddress of the modified domain.
*/
ObjectAddress
AlterDomainDropConstraint(List *names, const char *constrName,
*************** AlterDomainDropConstraint(List *names, c
*** 2455,2464 ****
Relation rel;
Relation conrel;
SysScanDesc conscan;
! ScanKeyData key[1];
HeapTuple contup;
bool found = false;
! ObjectAddress address = InvalidObjectAddress;
/* Make a TypeName so we can use standard type lookup machinery */
typename = makeTypeNameFromNameList(names);
--- 2457,2466 ----
Relation rel;
Relation conrel;
SysScanDesc conscan;
! ScanKeyData skey[3];
HeapTuple contup;
bool found = false;
! ObjectAddress address;
/* Make a TypeName so we can use standard type lookup machinery */
typename = makeTypeNameFromNameList(names);
*************** AlterDomainDropConstraint(List *names, c
*** 2477,2513 ****
/* Grab an appropriate lock on the pg_constraint relation */
conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
! /* Use the index to scan only constraints of the target relation */
! ScanKeyInit(&key[0],
Anum_pg_constraint_contypid,
BTEqualStrategyNumber, F_OIDEQ,
! ObjectIdGetDatum(HeapTupleGetOid(tup)));
! conscan = systable_beginscan(conrel, ConstraintTypidIndexId, true,
! NULL, 1, key);
! /*
! * Scan over the result set, removing any matching entries.
! */
! while ((contup = systable_getnext(conscan)) != NULL)
{
! Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(contup);
!
! if (strcmp(NameStr(con->conname), constrName) == 0)
! {
! ObjectAddress conobj;
! conobj.classId = ConstraintRelationId;
! conobj.objectId = HeapTupleGetOid(contup);
! conobj.objectSubId = 0;
! performDeletion(&conobj, behavior, 0);
! found = true;
! }
}
- ObjectAddressSet(address, TypeRelationId, domainoid);
-
/* Clean up after the scan */
systable_endscan(conscan);
heap_close(conrel, RowExclusiveLock);
--- 2479,2514 ----
/* Grab an appropriate lock on the pg_constraint relation */
conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
! /* Find and remove the target constraint */
! ScanKeyInit(&skey[0],
! Anum_pg_constraint_conrelid,
! BTEqualStrategyNumber, F_OIDEQ,
! ObjectIdGetDatum(InvalidOid));
! ScanKeyInit(&skey[1],
Anum_pg_constraint_contypid,
BTEqualStrategyNumber, F_OIDEQ,
! ObjectIdGetDatum(domainoid));
! ScanKeyInit(&skey[2],
! Anum_pg_constraint_conname,
! BTEqualStrategyNumber, F_NAMEEQ,
! CStringGetDatum(constrName));
! conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
! NULL, 3, skey);
! /* There can be at most one matching row */
! if ((contup = systable_getnext(conscan)) != NULL)
{
! ObjectAddress conobj;
! conobj.classId = ConstraintRelationId;
! conobj.objectId = HeapTupleGetOid(contup);
! conobj.objectSubId = 0;
! performDeletion(&conobj, behavior, 0);
! found = true;
}
/* Clean up after the scan */
systable_endscan(conscan);
heap_close(conrel, RowExclusiveLock);
*************** AlterDomainDropConstraint(List *names, c
*** 2527,2532 ****
--- 2528,2535 ----
constrName, TypeNameToString(typename))));
}
+ ObjectAddressSet(address, TypeRelationId, domainoid);
+
return address;
}
*************** AlterDomainValidateConstraint(List *name
*** 2652,2667 ****
Relation typrel;
Relation conrel;
HeapTuple tup;
! Form_pg_constraint con = NULL;
Form_pg_constraint copy_con;
char *conbin;
SysScanDesc scan;
Datum val;
- bool found = false;
bool isnull;
HeapTuple tuple;
HeapTuple copyTuple;
! ScanKeyData key;
ObjectAddress address;
/* Make a TypeName so we can use standard type lookup machinery */
--- 2655,2669 ----
Relation typrel;
Relation conrel;
HeapTuple tup;
! Form_pg_constraint con;
Form_pg_constraint copy_con;
char *conbin;
SysScanDesc scan;
Datum val;
bool isnull;
HeapTuple tuple;
HeapTuple copyTuple;
! ScanKeyData skey[3];
ObjectAddress address;
/* Make a TypeName so we can use standard type lookup machinery */
*************** AlterDomainValidateConstraint(List *name
*** 2682,2710 ****
* Find and check the target constraint
*/
conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
! ScanKeyInit(&key,
Anum_pg_constraint_contypid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(domainoid));
! scan = systable_beginscan(conrel, ConstraintTypidIndexId,
! true, NULL, 1, &key);
! while (HeapTupleIsValid(tuple = systable_getnext(scan)))
! {
! con = (Form_pg_constraint) GETSTRUCT(tuple);
! if (strcmp(NameStr(con->conname), constrName) == 0)
! {
! found = true;
! break;
! }
! }
! if (!found)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("constraint \"%s\" of domain \"%s\" does not exist",
constrName, TypeNameToString(typename))));
if (con->contype != CONSTRAINT_CHECK)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
--- 2684,2714 ----
* Find and check the target constraint
*/
conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
!
! ScanKeyInit(&skey[0],
! Anum_pg_constraint_conrelid,
! BTEqualStrategyNumber, F_OIDEQ,
! ObjectIdGetDatum(InvalidOid));
! ScanKeyInit(&skey[1],
Anum_pg_constraint_contypid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(domainoid));
! ScanKeyInit(&skey[2],
! Anum_pg_constraint_conname,
! BTEqualStrategyNumber, F_NAMEEQ,
! CStringGetDatum(constrName));
! scan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
! NULL, 3, skey);
! /* There can be at most one matching row */
! if (!HeapTupleIsValid(tuple = systable_getnext(scan)))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("constraint \"%s\" of domain \"%s\" does not exist",
constrName, TypeNameToString(typename))));
+ con = (Form_pg_constraint) GETSTRUCT(tuple);
if (con->contype != CONSTRAINT_CHECK)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 6125421..a4fc001 100644
*** a/src/backend/utils/cache/relcache.c
--- b/src/backend/utils/cache/relcache.c
*************** CheckConstraintFetch(Relation relation)
*** 4016,4022 ****
ObjectIdGetDatum(RelationGetRelid(relation)));
conrel = heap_open(ConstraintRelationId, AccessShareLock);
! conscan = systable_beginscan(conrel, ConstraintRelidIndexId, true,
NULL, 1, skey);
while (HeapTupleIsValid(htup = systable_getnext(conscan)))
--- 4016,4022 ----
ObjectIdGetDatum(RelationGetRelid(relation)));
conrel = heap_open(ConstraintRelationId, AccessShareLock);
! conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
NULL, 1, skey);
while (HeapTupleIsValid(htup = systable_getnext(conscan)))
*************** RelationGetFKeyList(Relation relation)
*** 4127,4133 ****
ObjectIdGetDatum(RelationGetRelid(relation)));
conrel = heap_open(ConstraintRelationId, AccessShareLock);
! conscan = systable_beginscan(conrel, ConstraintRelidIndexId, true,
NULL, 1, &skey);
while (HeapTupleIsValid(htup = systable_getnext(conscan)))
--- 4127,4133 ----
ObjectIdGetDatum(RelationGetRelid(relation)));
conrel = heap_open(ConstraintRelationId, AccessShareLock);
! conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
NULL, 1, &skey);
while (HeapTupleIsValid(htup = systable_getnext(conscan)))
*************** RelationGetExclusionInfo(Relation indexR
*** 5105,5110 ****
--- 5105,5114 ----
* Search pg_constraint for the constraint associated with the index. To
* make this not too painfully slow, we use the index on conrelid; that
* will hold the parent relation's OID not the index's own OID.
+ *
+ * Note: if we wanted to rely on the constraint name matching the index's
+ * name, we could just do a direct lookup using pg_constraint's unique
+ * index. For the moment it doesn't seem worth requiring that.
*/
ScanKeyInit(&skey[0],
Anum_pg_constraint_conrelid,
*************** RelationGetExclusionInfo(Relation indexR
*** 5112,5118 ****
ObjectIdGetDatum(indexRelation->rd_index->indrelid));
conrel = heap_open(ConstraintRelationId, AccessShareLock);
! conscan = systable_beginscan(conrel, ConstraintRelidIndexId, true,
NULL, 1, skey);
found = false;
--- 5116,5122 ----
ObjectIdGetDatum(indexRelation->rd_index->indrelid));
conrel = heap_open(ConstraintRelationId, AccessShareLock);
! conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
NULL, 1, skey);
found = false;
diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h
index 2491582..254fbef 100644
*** a/src/include/catalog/indexing.h
--- b/src/include/catalog/indexing.h
*************** DECLARE_UNIQUE_INDEX(pg_collation_oid_in
*** 121,128 ****
DECLARE_INDEX(pg_constraint_conname_nsp_index, 2664, on pg_constraint using btree(conname name_ops, connamespace oid_ops));
#define ConstraintNameNspIndexId 2664
! DECLARE_INDEX(pg_constraint_conrelid_index, 2665, on pg_constraint using btree(conrelid oid_ops));
! #define ConstraintRelidIndexId 2665
DECLARE_INDEX(pg_constraint_contypid_index, 2666, on pg_constraint using btree(contypid oid_ops));
#define ConstraintTypidIndexId 2666
DECLARE_UNIQUE_INDEX(pg_constraint_oid_index, 2667, on pg_constraint using btree(oid oid_ops));
--- 121,128 ----
DECLARE_INDEX(pg_constraint_conname_nsp_index, 2664, on pg_constraint using btree(conname name_ops, connamespace oid_ops));
#define ConstraintNameNspIndexId 2664
! DECLARE_UNIQUE_INDEX(pg_constraint_conrelid_contypid_conname_index, 2665, on pg_constraint using btree(conrelid oid_ops, contypid oid_ops, conname name_ops));
! #define ConstraintRelidTypidNameIndexId 2665
DECLARE_INDEX(pg_constraint_contypid_index, 2666, on pg_constraint using btree(contypid oid_ops));
#define ConstraintTypidIndexId 2666
DECLARE_UNIQUE_INDEX(pg_constraint_oid_index, 2667, on pg_constraint using btree(oid oid_ops));
diff --git a/src/include/catalog/pg_constraint.h b/src/include/catalog/pg_constraint.h
index 7c1c0e1..4435310 100644
*** a/src/include/catalog/pg_constraint.h
--- b/src/include/catalog/pg_constraint.h
*************** CATALOG(pg_constraint,2606,ConstraintRel
*** 39,44 ****
--- 39,48 ----
* global lock to generate a globally unique name for a nameless
* constraint. We associate a namespace with constraint names only for
* SQL-spec compatibility.
+ *
+ * However, we do require conname to be unique among the constraints of a
+ * single relation or domain. This is enforced by a unique index on
+ * conrelid + contypid + conname.
*/
NameData conname; /* name of this constraint */
Oid connamespace; /* OID of namespace containing constraint */