📄 pg_constraint.c
字号:
/*------------------------------------------------------------------------- * * pg_constraint.c * routines to support manipulation of the pg_constraint relation * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $PostgreSQL: pgsql/src/backend/catalog/pg_constraint.c,v 1.27.2.1 2005/11/22 18:23:06 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/heapam.h"#include "access/genam.h"#include "catalog/catalog.h"#include "catalog/dependency.h"#include "catalog/indexing.h"#include "catalog/pg_constraint.h"#include "catalog/pg_depend.h"#include "catalog/pg_trigger.h"#include "catalog/pg_type.h"#include "commands/defrem.h"#include "miscadmin.h"#include "utils/array.h"#include "utils/builtins.h"#include "utils/fmgroids.h"#include "utils/lsyscache.h"#include "utils/syscache.h"/* * CreateConstraintEntry * Create a constraint table entry. * * Subsidiary records (such as triggers or indexes to implement the * constraint) are *not* created here. But we do make dependency links * from the constraint to the things it depends on. */OidCreateConstraintEntry(const char *constraintName, Oid constraintNamespace, char constraintType, bool isDeferrable, bool isDeferred, Oid relId, const int16 *constraintKey, int constraintNKeys, Oid domainId, Oid foreignRelId, const int16 *foreignKey, int foreignNKeys, char foreignUpdateType, char foreignDeleteType, char foreignMatchType, Oid indexRelId, Node *conExpr, const char *conBin, const char *conSrc){ Relation conDesc; Oid conOid; HeapTuple tup; char nulls[Natts_pg_constraint]; Datum values[Natts_pg_constraint]; ArrayType *conkeyArray; ArrayType *confkeyArray; NameData cname; int i; ObjectAddress conobject; conDesc = heap_open(ConstraintRelationId, RowExclusiveLock); Assert(constraintName); namestrcpy(&cname, constraintName); /* * Convert C arrays into Postgres arrays. */ if (constraintNKeys > 0) { Datum *conkey; conkey = (Datum *) palloc(constraintNKeys * sizeof(Datum)); for (i = 0; i < constraintNKeys; i++) conkey[i] = Int16GetDatum(constraintKey[i]); conkeyArray = construct_array(conkey, constraintNKeys, INT2OID, 2, true, 's'); } else conkeyArray = NULL; if (foreignNKeys > 0) { Datum *confkey; confkey = (Datum *) palloc(foreignNKeys * sizeof(Datum)); for (i = 0; i < foreignNKeys; i++) confkey[i] = Int16GetDatum(foreignKey[i]); confkeyArray = construct_array(confkey, foreignNKeys, INT2OID, 2, true, 's'); } else confkeyArray = NULL; /* initialize nulls and values */ for (i = 0; i < Natts_pg_constraint; i++) { nulls[i] = ' '; values[i] = (Datum) NULL; } values[Anum_pg_constraint_conname - 1] = NameGetDatum(&cname); values[Anum_pg_constraint_connamespace - 1] = ObjectIdGetDatum(constraintNamespace); values[Anum_pg_constraint_contype - 1] = CharGetDatum(constraintType); values[Anum_pg_constraint_condeferrable - 1] = BoolGetDatum(isDeferrable); values[Anum_pg_constraint_condeferred - 1] = BoolGetDatum(isDeferred); values[Anum_pg_constraint_conrelid - 1] = ObjectIdGetDatum(relId); values[Anum_pg_constraint_contypid - 1] = ObjectIdGetDatum(domainId); values[Anum_pg_constraint_confrelid - 1] = ObjectIdGetDatum(foreignRelId); values[Anum_pg_constraint_confupdtype - 1] = CharGetDatum(foreignUpdateType); values[Anum_pg_constraint_confdeltype - 1] = CharGetDatum(foreignDeleteType); values[Anum_pg_constraint_confmatchtype - 1] = CharGetDatum(foreignMatchType); if (conkeyArray) values[Anum_pg_constraint_conkey - 1] = PointerGetDatum(conkeyArray); else nulls[Anum_pg_constraint_conkey - 1] = 'n'; if (confkeyArray) values[Anum_pg_constraint_confkey - 1] = PointerGetDatum(confkeyArray); else nulls[Anum_pg_constraint_confkey - 1] = 'n'; /* * initialize the binary form of the check constraint. */ if (conBin) values[Anum_pg_constraint_conbin - 1] = DirectFunctionCall1(textin, CStringGetDatum(conBin)); else nulls[Anum_pg_constraint_conbin - 1] = 'n'; /* * initialize the text form of the check constraint */ if (conSrc) values[Anum_pg_constraint_consrc - 1] = DirectFunctionCall1(textin, CStringGetDatum(conSrc)); else nulls[Anum_pg_constraint_consrc - 1] = 'n'; tup = heap_formtuple(RelationGetDescr(conDesc), values, nulls); conOid = simple_heap_insert(conDesc, tup); /* update catalog indexes */ CatalogUpdateIndexes(conDesc, tup); conobject.classId = ConstraintRelationId; conobject.objectId = conOid; conobject.objectSubId = 0; heap_close(conDesc, RowExclusiveLock); if (OidIsValid(relId)) { /* * Register auto dependency from constraint to owning relation, or to * specific column(s) if any are mentioned. */ ObjectAddress relobject; relobject.classId = RelationRelationId; relobject.objectId = relId; if (constraintNKeys > 0) { for (i = 0; i < constraintNKeys; i++) { relobject.objectSubId = constraintKey[i]; recordDependencyOn(&conobject, &relobject, DEPENDENCY_AUTO); } } else { relobject.objectSubId = 0; recordDependencyOn(&conobject, &relobject, DEPENDENCY_AUTO); } } if (OidIsValid(domainId)) { /* * Register auto dependency from constraint to owning domain */ ObjectAddress domobject; domobject.classId = TypeRelationId; domobject.objectId = domainId; domobject.objectSubId = 0; recordDependencyOn(&conobject, &domobject, DEPENDENCY_AUTO); } if (OidIsValid(foreignRelId)) { /* * Register normal dependency from constraint to foreign relation, or * to specific column(s) if any are mentioned. */ ObjectAddress relobject; relobject.classId = RelationRelationId; relobject.objectId = foreignRelId; if (foreignNKeys > 0) { for (i = 0; i < foreignNKeys; i++) { relobject.objectSubId = foreignKey[i]; recordDependencyOn(&conobject, &relobject, DEPENDENCY_NORMAL); } } else { relobject.objectSubId = 0; recordDependencyOn(&conobject, &relobject, DEPENDENCY_NORMAL); } } if (OidIsValid(indexRelId)) { /* * Register normal dependency on the unique index that supports a * foreign-key constraint. */ ObjectAddress relobject; relobject.classId = RelationRelationId; relobject.objectId = indexRelId; relobject.objectSubId = 0; recordDependencyOn(&conobject, &relobject, DEPENDENCY_NORMAL); } if (conExpr != NULL) { /* * Register dependencies from constraint to objects mentioned in CHECK * expression. */ recordDependencyOnSingleRelExpr(&conobject, conExpr, relId, DEPENDENCY_NORMAL, DEPENDENCY_NORMAL); } return conOid;}/* * Test whether given name is currently used as a constraint name * for the given object (relation or domain). * * This is used to decide whether to accept a user-specified constraint name. * It is deliberately not the same test as ChooseConstraintName uses to decide * whether an auto-generated name is OK: here, we will allow it unless there * is an identical constraint name in use *on the same object*. * * NB: Caller should hold exclusive lock on the given object, else * this test can be fooled by concurrent additions. */boolConstraintNameIsUsed(ConstraintCategory conCat, Oid objId, Oid objNamespace, const char *conname){ bool found; Relation conDesc; SysScanDesc conscan; ScanKeyData skey[2]; HeapTuple tup; conDesc = heap_open(ConstraintRelationId, AccessShareLock); found = false; ScanKeyInit(&skey[0], Anum_pg_constraint_conname, BTEqualStrategyNumber, F_NAMEEQ, CStringGetDatum(conname)); ScanKeyInit(&skey[1], Anum_pg_constraint_connamespace, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(objNamespace)); conscan = systable_beginscan(conDesc, ConstraintNameNspIndexId, true, SnapshotNow, 2, skey); while (HeapTupleIsValid(tup = systable_getnext(conscan))) { Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tup); if (conCat == CONSTRAINT_RELATION && con->conrelid == objId) { found = true; break; } else if (conCat == CONSTRAINT_DOMAIN && con->contypid == objId) { found = true; break; } } systable_endscan(conscan); heap_close(conDesc, AccessShareLock); return found;}/* * Select a nonconflicting name for a new constraint. * * The objective here is to choose a name that is unique within the * specified namespace. Postgres does not require this, but the SQL * spec does, and some apps depend on it. Therefore we avoid choosing * default names that so conflict.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -