diff options
Diffstat (limited to 'src/backend/catalog/pg_constraint.c')
-rw-r--r-- | src/backend/catalog/pg_constraint.c | 188 |
1 files changed, 80 insertions, 108 deletions
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c index 53249facb7..ede6607b85 100644 --- a/src/backend/catalog/pg_constraint.c +++ b/src/backend/catalog/pg_constraint.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/pg_constraint.c,v 1.34 2007/01/05 22:19:25 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/pg_constraint.c,v 1.35 2007/02/14 01:58:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,8 +19,7 @@ #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_operator.h" #include "catalog/pg_type.h" #include "commands/defrem.h" #include "utils/array.h" @@ -49,6 +48,9 @@ CreateConstraintEntry(const char *constraintName, Oid domainId, Oid foreignRelId, const int16 *foreignKey, + const Oid *pfEqOp, + const Oid *ppEqOp, + const Oid *ffEqOp, int foreignNKeys, char foreignUpdateType, char foreignDeleteType, @@ -65,6 +67,9 @@ CreateConstraintEntry(const char *constraintName, Datum values[Natts_pg_constraint]; ArrayType *conkeyArray; ArrayType *confkeyArray; + ArrayType *conpfeqopArray; + ArrayType *conppeqopArray; + ArrayType *conffeqopArray; NameData cname; int i; ObjectAddress conobject; @@ -92,16 +97,33 @@ CreateConstraintEntry(const char *constraintName, if (foreignNKeys > 0) { - Datum *confkey; + Datum *fkdatums; - confkey = (Datum *) palloc(foreignNKeys * sizeof(Datum)); + fkdatums = (Datum *) palloc(foreignNKeys * sizeof(Datum)); for (i = 0; i < foreignNKeys; i++) - confkey[i] = Int16GetDatum(foreignKey[i]); - confkeyArray = construct_array(confkey, foreignNKeys, + fkdatums[i] = Int16GetDatum(foreignKey[i]); + confkeyArray = construct_array(fkdatums, foreignNKeys, INT2OID, 2, true, 's'); + for (i = 0; i < foreignNKeys; i++) + fkdatums[i] = ObjectIdGetDatum(pfEqOp[i]); + conpfeqopArray = construct_array(fkdatums, foreignNKeys, + OIDOID, sizeof(Oid), true, 'i'); + for (i = 0; i < foreignNKeys; i++) + fkdatums[i] = ObjectIdGetDatum(ppEqOp[i]); + conppeqopArray = construct_array(fkdatums, foreignNKeys, + OIDOID, sizeof(Oid), true, 'i'); + for (i = 0; i < foreignNKeys; i++) + fkdatums[i] = ObjectIdGetDatum(ffEqOp[i]); + conffeqopArray = construct_array(fkdatums, foreignNKeys, + OIDOID, sizeof(Oid), true, 'i'); } else + { confkeyArray = NULL; + conpfeqopArray = NULL; + conppeqopArray = NULL; + conffeqopArray = NULL; + } /* initialize nulls and values */ for (i = 0; i < Natts_pg_constraint; i++) @@ -132,6 +154,21 @@ CreateConstraintEntry(const char *constraintName, else nulls[Anum_pg_constraint_confkey - 1] = 'n'; + if (conpfeqopArray) + values[Anum_pg_constraint_conpfeqop - 1] = PointerGetDatum(conpfeqopArray); + else + nulls[Anum_pg_constraint_conpfeqop - 1] = 'n'; + + if (conppeqopArray) + values[Anum_pg_constraint_conppeqop - 1] = PointerGetDatum(conppeqopArray); + else + nulls[Anum_pg_constraint_conppeqop - 1] = 'n'; + + if (conffeqopArray) + values[Anum_pg_constraint_conffeqop - 1] = PointerGetDatum(conffeqopArray); + else + nulls[Anum_pg_constraint_conffeqop - 1] = 'n'; + /* * initialize the binary form of the check constraint. */ @@ -246,6 +283,36 @@ CreateConstraintEntry(const char *constraintName, recordDependencyOn(&conobject, &relobject, DEPENDENCY_NORMAL); } + if (foreignNKeys > 0) + { + /* + * Register normal dependencies on the equality operators that + * support a foreign-key constraint. If the PK and FK types + * are the same then all three operators for a column are the + * same; otherwise they are different. + */ + ObjectAddress oprobject; + + oprobject.classId = OperatorRelationId; + oprobject.objectSubId = 0; + + for (i = 0; i < foreignNKeys; i++) + { + oprobject.objectId = pfEqOp[i]; + recordDependencyOn(&conobject, &oprobject, DEPENDENCY_NORMAL); + if (ppEqOp[i] != pfEqOp[i]) + { + oprobject.objectId = ppEqOp[i]; + recordDependencyOn(&conobject, &oprobject, DEPENDENCY_NORMAL); + } + if (ffEqOp[i] != pfEqOp[i]) + { + oprobject.objectId = ffEqOp[i]; + recordDependencyOn(&conobject, &oprobject, DEPENDENCY_NORMAL); + } + } + } + if (conExpr != NULL) { /* @@ -419,24 +486,16 @@ void RemoveConstraintById(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); + tup = SearchSysCache(CONSTROID, + ObjectIdGetDatum(conId), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) /* should not happen */ + elog(ERROR, "cache lookup failed for constraint %u", conId); con = (Form_pg_constraint) GETSTRUCT(tup); /* @@ -505,98 +564,11 @@ RemoveConstraintById(Oid conId) simple_heap_delete(conDesc, &tup->t_self); /* Clean up */ - systable_endscan(conscan); + ReleaseSysCache(tup); 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. |