📄 pg_constraint.c
字号:
* * name1, name2, and label are used the same way as for makeObjectName(), * 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. * * 'others' can be a list of string names already chosen within the current * command (but not yet reflected into the catalogs); we will not choose * a duplicate of one of these either. * * 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 * the relation identified by name1. * * Returns a palloc'd string. */char *ChooseConstraintName(const char *name1, const char *name2, const char *label, Oid namespace, List *others){ int pass = 0; char *conname = NULL; char modlabel[NAMEDATALEN]; Relation conDesc; SysScanDesc conscan; ScanKeyData skey[2]; bool found; ListCell *l; conDesc = heap_open(ConstraintRelationId, AccessShareLock); /* try the unmodified label first */ StrNCpy(modlabel, label, sizeof(modlabel)); for (;;) { conname = makeObjectName(name1, name2, modlabel); found = false; foreach(l, others) { if (strcmp((char *) lfirst(l), conname) == 0) { found = true; break; } } if (!found) { ScanKeyInit(&skey[0], Anum_pg_constraint_conname, BTEqualStrategyNumber, F_NAMEEQ, CStringGetDatum(conname)); ScanKeyInit(&skey[1], Anum_pg_constraint_connamespace, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(namespace)); conscan = systable_beginscan(conDesc, ConstraintNameNspIndexId, true, SnapshotNow, 2, skey); found = (HeapTupleIsValid(systable_getnext(conscan))); systable_endscan(conscan); } if (!found) break; /* found a conflict, so try a new name component */ pfree(conname); snprintf(modlabel, sizeof(modlabel), "%s%d", label, ++pass); } heap_close(conDesc, AccessShareLock); return conname;}/* * Delete a single constraint record. */voidRemoveConstraintById(Oid conId){ Relation conDesc; ScanKeyData skey[1]; SysScanDesc conscan; HeapTuple tup; Form_pg_constraint con; conDesc = heap_open(ConstraintRelationId, RowExclusiveLock); ScanKeyInit(&skey[0], ObjectIdAttributeNumber, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(conId)); conscan = systable_beginscan(conDesc, ConstraintOidIndexId, true, SnapshotNow, 1, skey); tup = systable_getnext(conscan); if (!HeapTupleIsValid(tup)) elog(ERROR, "could not find tuple for constraint %u", conId); con = (Form_pg_constraint) GETSTRUCT(tup); /* * Special processing depending on what the constraint is for. */ if (OidIsValid(con->conrelid)) { Relation rel; /* * If the constraint is for a relation, open and exclusive-lock the * relation it's for. */ rel = heap_open(con->conrelid, AccessExclusiveLock); /* * We need to update the relcheck count if it is a check constraint * being dropped. This update will force backends to rebuild relcache * entries when we commit. */ if (con->contype == CONSTRAINT_CHECK) { Relation pgrel; HeapTuple relTup; Form_pg_class classForm; pgrel = heap_open(RelationRelationId, RowExclusiveLock); relTup = SearchSysCacheCopy(RELOID, ObjectIdGetDatum(con->conrelid), 0, 0, 0); if (!HeapTupleIsValid(relTup)) elog(ERROR, "cache lookup failed for relation %u", con->conrelid); classForm = (Form_pg_class) GETSTRUCT(relTup); if (classForm->relchecks == 0) /* should not happen */ elog(ERROR, "relation \"%s\" has relchecks = 0", RelationGetRelationName(rel)); classForm->relchecks--; simple_heap_update(pgrel, &relTup->t_self, relTup); CatalogUpdateIndexes(pgrel, relTup); heap_freetuple(relTup); heap_close(pgrel, RowExclusiveLock); } /* Keep lock on constraint's rel until end of xact */ heap_close(rel, NoLock); } else if (OidIsValid(con->contypid)) { /* * XXX for now, do nothing special when dropping a domain constraint * * Probably there should be some form of locking on the domain type, * but we have no such concept at the moment. */ } else elog(ERROR, "constraint %u is not of a known type", conId); /* Fry the constraint itself */ simple_heap_delete(conDesc, &tup->t_self); /* Clean up */ systable_endscan(conscan); heap_close(conDesc, RowExclusiveLock);}/* * GetConstraintNameForTrigger * Get the name of the constraint owning a trigger, if any * * Returns a palloc'd string, or NULL if no constraint can be found */char *GetConstraintNameForTrigger(Oid triggerId){ char *result; Oid constraintId = InvalidOid; Relation depRel; Relation conRel; ScanKeyData key[2]; SysScanDesc scan; HeapTuple tup; /* * We must grovel through pg_depend to find the owning constraint. Perhaps * pg_trigger should have a column for the owning constraint ... but right * now this is not performance-critical code. */ depRel = heap_open(DependRelationId, AccessShareLock); ScanKeyInit(&key[0], Anum_pg_depend_classid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(TriggerRelationId)); ScanKeyInit(&key[1], Anum_pg_depend_objid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(triggerId)); /* assume we can ignore objsubid for a trigger */ scan = systable_beginscan(depRel, DependDependerIndexId, true, SnapshotNow, 2, key); while (HeapTupleIsValid(tup = systable_getnext(scan))) { Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup); if (foundDep->refclassid == ConstraintRelationId && foundDep->deptype == DEPENDENCY_INTERNAL) { constraintId = foundDep->refobjid; break; } } systable_endscan(scan); heap_close(depRel, AccessShareLock); if (!OidIsValid(constraintId)) return NULL; /* no owning constraint found */ conRel = heap_open(ConstraintRelationId, AccessShareLock); ScanKeyInit(&key[0], ObjectIdAttributeNumber, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(constraintId)); scan = systable_beginscan(conRel, ConstraintOidIndexId, true, SnapshotNow, 1, key); tup = systable_getnext(scan); if (HeapTupleIsValid(tup)) { Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tup); result = pstrdup(NameStr(con->conname)); } else { /* This arguably should be an error, but we'll just return NULL */ result = NULL; } systable_endscan(scan); heap_close(conRel, AccessShareLock); return result;}/* * AlterConstraintNamespaces * Find any constraints belonging to the specified object, * and move them to the specified new namespace. * * isType indicates whether the owning object is a type or a relation. */voidAlterConstraintNamespaces(Oid ownerId, Oid oldNspId, Oid newNspId, bool isType){ 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, SnapshotNow, 1, key); } else { ScanKeyInit(&key[0], Anum_pg_constraint_conrelid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(ownerId)); scan = systable_beginscan(conRel, ConstraintRelidIndexId, true, SnapshotNow, 1, key); } while (HeapTupleIsValid((tup = systable_getnext(scan)))) { Form_pg_constraint conform = (Form_pg_constraint) GETSTRUCT(tup); if (conform->connamespace == oldNspId) { tup = heap_copytuple(tup); conform = (Form_pg_constraint) GETSTRUCT(tup); conform->connamespace = newNspId; simple_heap_update(conRel, &tup->t_self, tup); CatalogUpdateIndexes(conRel, tup); /* * Note: currently, the constraint will not have its own * dependency on the namespace, so we don't need to do * changeDependencyFor(). */ } } systable_endscan(scan); heap_close(conRel, RowExclusiveLock);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -