aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands')
-rw-r--r--src/backend/commands/indexcmds.c27
-rw-r--r--src/backend/commands/tablecmds.c138
-rw-r--r--src/backend/commands/typecmds.c85
3 files changed, 134 insertions, 116 deletions
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index d54c78c3527..ab3d9a0a489 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1995,6 +1995,12 @@ makeObjectName(const char *name1, const char *name2, const char *label)
* except that the label can't be NULL; digits will be appended to the label
* if needed to create a name that is unique within the specified namespace.
*
+ * If isconstraint is true, we also avoid choosing a name matching any
+ * existing constraint in the same namespace. (This is stricter than what
+ * Postgres itself requires, but the SQL standard says that constraint names
+ * should be unique within schemas, so we follow that for autogenerated
+ * constraint names.)
+ *
* Note: it is theoretically possible to get a collision anyway, if someone
* else chooses the same name concurrently. This is fairly unlikely to be
* a problem in practice, especially if one is holding an exclusive lock on
@@ -2006,7 +2012,8 @@ makeObjectName(const char *name1, const char *name2, const char *label)
*/
char *
ChooseRelationName(const char *name1, const char *name2,
- const char *label, Oid namespaceid)
+ const char *label, Oid namespaceid,
+ bool isconstraint)
{
int pass = 0;
char *relname = NULL;
@@ -2020,7 +2027,11 @@ ChooseRelationName(const char *name1, const char *name2,
relname = makeObjectName(name1, name2, modlabel);
if (!OidIsValid(get_relname_relid(relname, namespaceid)))
- break;
+ {
+ if (!isconstraint ||
+ !ConstraintNameExists(relname, namespaceid))
+ break;
+ }
/* found a conflict, so try a new name component */
pfree(relname);
@@ -2048,28 +2059,32 @@ ChooseIndexName(const char *tabname, Oid namespaceId,
indexname = ChooseRelationName(tabname,
NULL,
"pkey",
- namespaceId);
+ namespaceId,
+ true);
}
else if (exclusionOpNames != NIL)
{
indexname = ChooseRelationName(tabname,
ChooseIndexNameAddition(colnames),
"excl",
- namespaceId);
+ namespaceId,
+ true);
}
else if (isconstraint)
{
indexname = ChooseRelationName(tabname,
ChooseIndexNameAddition(colnames),
"key",
- namespaceId);
+ namespaceId,
+ true);
}
else
{
indexname = ChooseRelationName(tabname,
ChooseIndexNameAddition(colnames),
"idx",
- namespaceId);
+ namespaceId,
+ false);
}
return indexname;
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index f46af41b562..f9e83c24565 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -7145,7 +7145,6 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
{
if (ConstraintNameIsUsed(CONSTRAINT_RELATION,
RelationGetRelid(rel),
- RelationGetNamespace(rel),
newConstraint->conname))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
@@ -7801,10 +7800,9 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd,
Constraint *cmdcon;
Relation conrel;
SysScanDesc scan;
- ScanKeyData key;
+ ScanKeyData skey[3];
HeapTuple contuple;
- Form_pg_constraint currcon = NULL;
- bool found = false;
+ Form_pg_constraint currcon;
ObjectAddress address;
cmdcon = castNode(Constraint, cmd->def);
@@ -7814,29 +7812,29 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd,
/*
* Find and check the target constraint
*/
- ScanKeyInit(&key,
+ ScanKeyInit(&skey[0],
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;
- }
- }
+ 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);
- if (!found)
+ /* 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),
@@ -7969,10 +7967,9 @@ ATExecValidateConstraint(Relation rel, char *constrName, bool recurse,
{
Relation conrel;
SysScanDesc scan;
- ScanKeyData key;
+ ScanKeyData skey[3];
HeapTuple tuple;
- Form_pg_constraint con = NULL;
- bool found = false;
+ Form_pg_constraint con;
ObjectAddress address;
conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
@@ -7980,29 +7977,29 @@ ATExecValidateConstraint(Relation rel, char *constrName, bool recurse,
/*
* Find and check the target constraint
*/
- ScanKeyInit(&key,
+ ScanKeyInit(&skey[0],
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;
- }
- }
+ 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);
- if (!found)
+ /* 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,
@@ -8865,7 +8862,7 @@ ATExecDropConstraint(Relation rel, const char *constrName,
Relation conrel;
Form_pg_constraint con;
SysScanDesc scan;
- ScanKeyData key;
+ ScanKeyData skey[3];
HeapTuple tuple;
bool found = false;
bool is_no_inherit_constraint = false;
@@ -8879,22 +8876,28 @@ ATExecDropConstraint(Relation rel, const char *constrName,
/*
* Find and drop the target constraint
*/
- ScanKeyInit(&key,
+ ScanKeyInit(&skey[0],
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(rel)));
- scan = systable_beginscan(conrel, ConstraintRelidIndexId,
- true, NULL, 1, &key);
+ 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);
- while (HeapTupleIsValid(tuple = systable_getnext(scan)))
+ /* There can be at most one matching row */
+ if (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,
@@ -8932,9 +8935,6 @@ ATExecDropConstraint(Relation rel, const char *constrName,
performDeletion(&conobj, behavior, 0);
found = true;
-
- /* constraint found and dropped -- no need to keep looping */
- break;
}
systable_endscan(scan);
@@ -8990,27 +8990,23 @@ ATExecDropConstraint(Relation rel, const char *constrName,
childrel = heap_open(childrelid, NoLock);
CheckTableNotInUse(childrel, "ALTER TABLE");
- ScanKeyInit(&key,
+ ScanKeyInit(&skey[0],
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))
+ 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",
@@ -9023,6 +9019,10 @@ ATExecDropConstraint(Relation rel, const char *constrName,
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);
@@ -11824,7 +11824,7 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel)
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(parent_rel)));
- parent_scan = systable_beginscan(catalog_relation, ConstraintRelidIndexId,
+ parent_scan = systable_beginscan(catalog_relation, ConstraintRelidTypidNameIndexId,
true, NULL, 1, &parent_key);
while (HeapTupleIsValid(parent_tuple = systable_getnext(parent_scan)))
@@ -11847,7 +11847,7 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel)
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(child_rel)));
- child_scan = systable_beginscan(catalog_relation, ConstraintRelidIndexId,
+ child_scan = systable_beginscan(catalog_relation, ConstraintRelidTypidNameIndexId,
true, NULL, 1, &child_key);
while (HeapTupleIsValid(child_tuple = systable_getnext(child_scan)))
@@ -12068,7 +12068,7 @@ RemoveInheritance(Relation child_rel, Relation parent_rel)
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(parent_rel)));
- scan = systable_beginscan(catalogRelation, ConstraintRelidIndexId,
+ scan = systable_beginscan(catalogRelation, ConstraintRelidTypidNameIndexId,
true, NULL, 1, key);
connames = NIL;
@@ -12088,7 +12088,7 @@ RemoveInheritance(Relation child_rel, Relation parent_rel)
Anum_pg_constraint_conrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(child_rel)));
- scan = systable_beginscan(catalogRelation, ConstraintRelidIndexId,
+ scan = systable_beginscan(catalogRelation, ConstraintRelidTypidNameIndexId,
true, NULL, 1, key);
while (HeapTupleIsValid(constraintTuple = systable_getnext(scan)))
@@ -12829,7 +12829,7 @@ ATPrepChangePersistence(Relation rel, bool toLogged)
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(rel)));
scan = systable_beginscan(pg_constraint,
- toLogged ? ConstraintRelidIndexId : InvalidOid,
+ 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 175ecc8b484..b018585aef8 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -2444,6 +2444,8 @@ AlterDomainNotNull(List *names, bool notNull)
* AlterDomainDropConstraint
*
* Implements the ALTER DOMAIN DROP CONSTRAINT statement
+ *
+ * Returns ObjectAddress of the modified domain.
*/
ObjectAddress
AlterDomainDropConstraint(List *names, const char *constrName,
@@ -2455,10 +2457,10 @@ AlterDomainDropConstraint(List *names, const char *constrName,
Relation rel;
Relation conrel;
SysScanDesc conscan;
- ScanKeyData key[1];
+ ScanKeyData skey[3];
HeapTuple contup;
bool found = false;
- ObjectAddress address = InvalidObjectAddress;
+ ObjectAddress address;
/* Make a TypeName so we can use standard type lookup machinery */
typename = makeTypeNameFromNameList(names);
@@ -2477,37 +2479,36 @@ AlterDomainDropConstraint(List *names, const char *constrName,
/* 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],
+ /* 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(HeapTupleGetOid(tup)));
+ ObjectIdGetDatum(domainoid));
+ ScanKeyInit(&skey[2],
+ Anum_pg_constraint_conname,
+ BTEqualStrategyNumber, F_NAMEEQ,
+ CStringGetDatum(constrName));
- conscan = systable_beginscan(conrel, ConstraintTypidIndexId, true,
- NULL, 1, key);
+ conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
+ NULL, 3, skey);
- /*
- * Scan over the result set, removing any matching entries.
- */
- while ((contup = systable_getnext(conscan)) != NULL)
+ /* There can be at most one matching row */
+ if ((contup = systable_getnext(conscan)) != NULL)
{
- Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(contup);
-
- if (strcmp(NameStr(con->conname), constrName) == 0)
- {
- ObjectAddress conobj;
+ ObjectAddress conobj;
- conobj.classId = ConstraintRelationId;
- conobj.objectId = HeapTupleGetOid(contup);
- conobj.objectSubId = 0;
+ conobj.classId = ConstraintRelationId;
+ conobj.objectId = HeapTupleGetOid(contup);
+ conobj.objectSubId = 0;
- performDeletion(&conobj, behavior, 0);
- found = true;
- }
+ performDeletion(&conobj, behavior, 0);
+ found = true;
}
- ObjectAddressSet(address, TypeRelationId, domainoid);
-
/* Clean up after the scan */
systable_endscan(conscan);
heap_close(conrel, RowExclusiveLock);
@@ -2527,6 +2528,8 @@ AlterDomainDropConstraint(List *names, const char *constrName,
constrName, TypeNameToString(typename))));
}
+ ObjectAddressSet(address, TypeRelationId, domainoid);
+
return address;
}
@@ -2652,16 +2655,15 @@ AlterDomainValidateConstraint(List *names, const char *constrName)
Relation typrel;
Relation conrel;
HeapTuple tup;
- Form_pg_constraint con = NULL;
+ Form_pg_constraint con;
Form_pg_constraint copy_con;
char *conbin;
SysScanDesc scan;
Datum val;
- bool found = false;
bool isnull;
HeapTuple tuple;
HeapTuple copyTuple;
- ScanKeyData key;
+ ScanKeyData skey[3];
ObjectAddress address;
/* Make a TypeName so we can use standard type lookup machinery */
@@ -2682,29 +2684,31 @@ AlterDomainValidateConstraint(List *names, const char *constrName)
* Find and check the target constraint
*/
conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
- ScanKeyInit(&key,
+
+ ScanKeyInit(&skey[0],
+ Anum_pg_constraint_conrelid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(InvalidOid));
+ ScanKeyInit(&skey[1],
Anum_pg_constraint_contypid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(domainoid));
- scan = systable_beginscan(conrel, ConstraintTypidIndexId,
- true, NULL, 1, &key);
+ ScanKeyInit(&skey[2],
+ Anum_pg_constraint_conname,
+ BTEqualStrategyNumber, F_NAMEEQ,
+ CStringGetDatum(constrName));
- while (HeapTupleIsValid(tuple = systable_getnext(scan)))
- {
- con = (Form_pg_constraint) GETSTRUCT(tuple);
- if (strcmp(NameStr(con->conname), constrName) == 0)
- {
- found = true;
- break;
- }
- }
+ scan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
+ NULL, 3, skey);
- if (!found)
+ /* 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),
@@ -3072,7 +3076,6 @@ domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid,
{
if (ConstraintNameIsUsed(CONSTRAINT_DOMAIN,
domainOid,
- domainNamespace,
constr->conname))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),