diff options
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/indexcmds.c | 27 | ||||
-rw-r--r-- | src/backend/commands/tablecmds.c | 138 | ||||
-rw-r--r-- | src/backend/commands/typecmds.c | 85 |
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), |