/* *CreateConstraintEntry *Createaconstrainttableentry. * *Subsidiaryrecords(suchastriggersorindexestoimplementthe *constraint)are*not*createdhere.Butwedomakedependencylinks *fromtheconstrainttothethingsitdependson. * *Thenewconstraint'sOIDisreturned.
*/
Oid
CreateConstraintEntry(constchar *constraintName,
Oid constraintNamespace, char constraintType, bool isDeferrable, bool isDeferred, bool isEnforced, bool isValidated,
Oid parentConstrId,
Oid relId, const int16 *constraintKey, int constraintNKeys, int constraintNTotalKeys,
Oid domainId,
Oid indexRelId,
Oid foreignRelId, const int16 *foreignKey, const Oid *pfEqOp, const Oid *ppEqOp, const Oid *ffEqOp, int foreignNKeys, char foreignUpdateType, char foreignDeleteType, const int16 *fkDeleteSetCols, int numFkDeleteSetCols, char foreignMatchType, const Oid *exclOp,
Node *conExpr, constchar *conBin, bool conIsLocal,
int16 conInhCount, bool conNoInherit, bool conPeriod, bool is_internal)
{
Relation conDesc;
Oid conOid;
HeapTuple tup; bool nulls[Natts_pg_constraint];
Datum values[Natts_pg_constraint];
ArrayType *conkeyArray;
ArrayType *confkeyArray;
ArrayType *conpfeqopArray;
ArrayType *conppeqopArray;
ArrayType *conffeqopArray;
ArrayType *conexclopArray;
ArrayType *confdelsetcolsArray;
NameData cname; int i;
ObjectAddress conobject;
ObjectAddresses *addrs_auto;
ObjectAddresses *addrs_normal;
/* Only CHECK or FOREIGN KEY constraint can be not enforced */
Assert(isEnforced || constraintType == CONSTRAINT_CHECK ||
constraintType == CONSTRAINT_FOREIGN); /* NOT ENFORCED constraint must be NOT VALID */
Assert(isEnforced || !isValidated);
pg_constraint = table_open(ConstraintRelationId, RowExclusiveLock);
conform = (Form_pg_constraint) GETSTRUCT(tup);
/* *IftheNOINHERITflagwe'reaskedfordoesn'tmatchwhatthe *existingconstrainthas,throwanerror.
*/ if (is_no_inherit != conform->connoinherit)
ereport(ERROR,
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("cannot change NO INHERIT status of NOT NULL constraint \"%s\" on relation \"%s\"",
NameStr(conform->conname), get_rel_name(relid)),
errhint("You might need to make the existing constraint inheritable using %s.", "ALTER TABLE ... ALTER CONSTRAINT ... INHERIT"));
/* *ThrowanerroriftheexistingconstraintisNOTVALIDandcaller *wantsavalidone.
*/ if (!is_notvalid && !conform->convalidated)
ereport(ERROR,
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("incompatible NOT VALID constraint \"%s\" on relation \"%s\"",
NameStr(conform->conname), get_rel_name(relid)),
errhint("You might need to validate it using %s.", "ALTER TABLE ... VALIDATE CONSTRAINT"));
/* *If,foranewconstraintthatisbeingdefinedlocally(i.e.,not *beingpasseddownviainheritance),anamewasspecified,then *verifythattheexistingconstrainthasthesamename.Otherwise *throwanerror.Namesofinheritedconstraintsareignoredbecause *theyarenotdirectlyuser-specified,somatchingisnotimportant.
*/ if (is_local && new_conname &&
strcmp(new_conname, NameStr(conform->conname)) != 0)
ereport(ERROR,
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("cannot create not-null constraint \"%s\" on column \"%s\" of table \"%s\"",
new_conname, get_attname(relid, attnum, false), get_rel_name(relid)),
errdetail("A not-null constraint named \"%s\" already exists for this column.",
NameStr(conform->conname)));
if (!is_local)
{ if (pg_add_s16_overflow(conform->coninhcount, 1,
&conform->coninhcount))
ereport(ERROR,
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many inheritance parents"));
changed = true;
} elseif (!conform->conislocal)
{
conform->conislocal = true;
changed = true;
}
if (changed)
CatalogTupleUpdate(pg_constraint, &tup->t_self, tup);
tup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(conId)); if (!HeapTupleIsValid(tup)) /* should not happen */
elog(ERROR, "cache lookup failed for constraint %u", conId);
con = (Form_pg_constraint) GETSTRUCT(tup);
/* *Specialprocessingdependingonwhattheconstraintisfor.
*/ if (OidIsValid(con->conrelid))
{
Relation rel;
if (classForm->relchecks == 0) /* should not happen */
elog(ERROR, "relation \"%s\" has relchecks = 0",
RelationGetRelationName(rel));
classForm->relchecks--;
/* Keep lock on constraint's rel until end of xact */
table_close(rel, NoLock);
} elseif (OidIsValid(con->contypid))
{ /* *XXXfornow,donothingspecialwhendroppingadomainconstraint * *Probablythereshouldbesomeformoflockingonthedomaintype, *butwehavenosuchconceptatthemoment.
*/
} else
elog(ERROR, "constraint %u is not of a known type", conId);
/* Fry the constraint itself */
CatalogTupleDelete(conDesc, &tup->t_self);
/* Clean up */
ReleaseSysCache(tup);
table_close(conDesc, RowExclusiveLock);
}
if (object_address_present(&thisobj, objsMoved)) continue;
/* Don't update if the object is already part of the namespace */ if (conform->connamespace == oldNspId && oldNspId != newNspId)
{
tup = heap_copytuple(tup);
conform = (Form_pg_constraint) GETSTRUCT(tup);
/* There can be at most one matching row */ if (HeapTupleIsValid(tuple = systable_getnext(scan)))
conOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
systable_endscan(scan);
/* If no such constraint exists, complain */ if (!OidIsValid(conOid) && !missing_ok)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("constraint \"%s\" for table \"%s\" does not exist",
conname, get_rel_name(relid))));
/* Extract the conkey array, ie, attnums of constrained columns */
adatum = heap_getattr(tuple, Anum_pg_constraint_conkey,
RelationGetDescr(pg_constraint), &isNull); if (!isNull)
{
ArrayType *arr; int numcols;
int16 *attnums; int i;
arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
numcols = ARR_DIMS(arr)[0]; if (ARR_NDIM(arr) != 1 ||
numcols < 0 ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != INT2OID)
elog(ERROR, "conkey is not a 1-D smallint array");
attnums = (int16 *) ARR_DATA_PTR(arr);
/* Construct the result value */ for (i = 0; i < numcols; i++)
{
conattnos = bms_add_member(conattnos,
attnums[i] - FirstLowInvalidHeapAttributeNumber);
}
}
}
systable_endscan(scan);
/* If no such constraint exists, complain */ if (!OidIsValid(*constraintOid) && !missing_ok)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("constraint \"%s\" for table \"%s\" does not exist",
conname, get_rel_name(relid))));
table_close(pg_constraint, AccessShareLock);
return conattnos;
}
/* *ReturntheOIDoftheconstraintenforcedbythegivenindexinthe *givenrelation;orInvalidOidifnosuchindexiscataloged. * *Muchlikeget_constraint_index,thisfunctionisconcernedonlywiththe *oneconstraintthat"owns"thegivenindex.Therefore,constraintsof *typesotherthanunique,primary-key,andexclusionareignored.
*/
Oid
get_relation_idx_constraint_oid(Oid relationId, Oid indexId)
{
Relation pg_constraint;
SysScanDesc scan;
ScanKeyData key;
HeapTuple tuple;
Oid constraintId = InvalidOid;
/* There can be at most one matching row */ if (HeapTupleIsValid(tuple = systable_getnext(scan)))
conOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
systable_endscan(scan);
/* If no such constraint exists, complain */ if (!OidIsValid(conOid) && !missing_ok)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("constraint \"%s\" for domain %s does not exist",
conname, format_type_be(typid))));
while (HeapTupleIsValid(tuple = systable_getnext(scan)))
{
Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
Datum adatum; bool isNull;
ArrayType *arr;
int16 *attnums; int numkeys; int i;
/* Skip constraints that are not PRIMARY KEYs */ if (con->contype != CONSTRAINT_PRIMARY) continue;
/* *Iftheprimarykeyisdeferrable,butwe'vebeeninstructedto *ignoredeferrableconstraints,thenwemightaswellgiveup *searching,sincetherecanonlybeasingleprimarykeyonatable.
*/ if (con->condeferrable && !deferrableOk) break;
/* Extract the conkey array, ie, attnums of PK's columns */
adatum = heap_getattr(tuple, Anum_pg_constraint_conkey,
RelationGetDescr(pg_constraint), &isNull); if (isNull)
elog(ERROR, "null conkey for constraint %u",
((Form_pg_constraint) GETSTRUCT(tuple))->oid);
arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
numkeys = ARR_DIMS(arr)[0]; if (ARR_NDIM(arr) != 1 ||
numkeys < 0 ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != INT2OID)
elog(ERROR, "conkey is not a 1-D smallint array");
attnums = (int16 *) ARR_DATA_PTR(arr);
/* Construct the result value */ for (i = 0; i < numkeys; i++)
{
pkattnos = bms_add_member(pkattnos,
attnums[i] - FirstLowInvalidHeapAttributeNumber);
}
*constraintOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
/* No need to search further */ break;
}
systable_endscan(scan);
table_close(pg_constraint, AccessShareLock);
return pkattnos;
}
/* *Extractdatafromthepg_constrainttupleofaforeign-keyconstraint. * *Allargumentssavethefirstareoutputarguments.Alloutputarguments *otherthannumfks,conkeyandconfkeycanbepassedasNULLifcaller *doesn'tneedthem.
*/ void
DeconstructFkConstraintRow(HeapTuple tuple, int *numfks,
AttrNumber *conkey, AttrNumber *confkey,
Oid *pf_eq_oprs, Oid *pp_eq_oprs, Oid *ff_eq_oprs, int *num_fk_del_set_cols, AttrNumber *fk_del_set_cols)
{
Datum adatum; bool isNull;
ArrayType *arr; int numkeys;
/* *Weexpectthearraystobe1-Darraysoftherighttypes;verifythat. *Wedon'tneedtousedeconstruct_array()sincethearraydataisjust *goingtolooklikeaCarrayofvalues.
*/
adatum = SysCacheGetAttrNotNull(CONSTROID, tuple,
Anum_pg_constraint_conkey);
arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */ if (ARR_NDIM(arr) != 1 ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != INT2OID)
elog(ERROR, "conkey is not a 1-D smallint array");
numkeys = ARR_DIMS(arr)[0]; if (numkeys <= 0 || numkeys > INDEX_MAX_KEYS)
elog(ERROR, "foreign key constraint cannot have %d columns", numkeys);
memcpy(conkey, ARR_DATA_PTR(arr), numkeys * sizeof(int16)); if ((Pointer) arr != DatumGetPointer(adatum))
pfree(arr); /* free de-toasted copy, if any */
adatum = SysCacheGetAttrNotNull(CONSTROID, tuple,
Anum_pg_constraint_confkey);
arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */ if (ARR_NDIM(arr) != 1 ||
ARR_DIMS(arr)[0] != numkeys ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != INT2OID)
elog(ERROR, "confkey is not a 1-D smallint array");
memcpy(confkey, ARR_DATA_PTR(arr), numkeys * sizeof(int16)); if ((Pointer) arr != DatumGetPointer(adatum))
pfree(arr); /* free de-toasted copy, if any */
if (pf_eq_oprs)
{
adatum = SysCacheGetAttrNotNull(CONSTROID, tuple,
Anum_pg_constraint_conpfeqop);
arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */ /* see TryReuseForeignKey if you change the test below */ if (ARR_NDIM(arr) != 1 ||
ARR_DIMS(arr)[0] != numkeys ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != OIDOID)
elog(ERROR, "conpfeqop is not a 1-D Oid array");
memcpy(pf_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid)); if ((Pointer) arr != DatumGetPointer(adatum))
pfree(arr); /* free de-toasted copy, if any */
}
if (pp_eq_oprs)
{
adatum = SysCacheGetAttrNotNull(CONSTROID, tuple,
Anum_pg_constraint_conppeqop);
arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */ if (ARR_NDIM(arr) != 1 ||
ARR_DIMS(arr)[0] != numkeys ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != OIDOID)
elog(ERROR, "conppeqop is not a 1-D Oid array");
memcpy(pp_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid)); if ((Pointer) arr != DatumGetPointer(adatum))
pfree(arr); /* free de-toasted copy, if any */
}
if (ff_eq_oprs)
{
adatum = SysCacheGetAttrNotNull(CONSTROID, tuple,
Anum_pg_constraint_conffeqop);
arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */ if (ARR_NDIM(arr) != 1 ||
ARR_DIMS(arr)[0] != numkeys ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != OIDOID)
elog(ERROR, "conffeqop is not a 1-D Oid array");
memcpy(ff_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid)); if ((Pointer) arr != DatumGetPointer(adatum))
pfree(arr); /* free de-toasted copy, if any */
}
if (fk_del_set_cols)
{
adatum = SysCacheGetAttr(CONSTROID, tuple,
Anum_pg_constraint_confdelsetcols, &isNull); if (isNull)
{
*num_fk_del_set_cols = 0;
} else
{ int num_delete_cols;
arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */ if (ARR_NDIM(arr) != 1 ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != INT2OID)
elog(ERROR, "confdelsetcols is not a 1-D smallint array");
num_delete_cols = ARR_DIMS(arr)[0];
memcpy(fk_del_set_cols, ARR_DATA_PTR(arr), num_delete_cols * sizeof(int16)); if ((Pointer) arr != DatumGetPointer(adatum))
pfree(arr); /* free de-toasted copy, if any */
*num_fk_del_set_cols = num_delete_cols;
}
}
*numfks = numkeys;
}
/* *FindFKPeriodOpers- * *LooksuptheoperatoroidsusedforthePERIODpartofatemporalforeignkey. *TheopclassshouldbetheopclassofthatPERIODelement. *Everythingelseisanoutput:containedbyoperoidistheContainedByoperatorfor *typesmatchingthePERIODelement. *aggedcontainedbyoperoidisalsoaContainedByoperator, *butonewhoserhsisamultirange. *Thatwayforeignkeyscancomparefkattr<@range_agg(pkattr). *intersectoperoidisusedbyNOACTIONconstraintstotrimtherangebeingconsidered *tojustwhatwasupdated/deleted.
*/ void
FindFKPeriodOpers(Oid opclass,
Oid *containedbyoperoid,
Oid *aggedcontainedbyoperoid,
Oid *intersectoperoid)
{
Oid opfamily = InvalidOid;
Oid opcintype = InvalidOid;
StrategyNumber strat;
/* Make sure we have a range or multirange. */ if (get_opclass_opfamily_and_input_type(opclass, &opfamily, &opcintype))
{ if (opcintype != ANYRANGEOID && opcintype != ANYMULTIRANGEOID)
ereport(ERROR,
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("invalid type for PERIOD part of foreign key"),
errdetail("Only range and multirange are supported."));
} else
elog(ERROR, "cache lookup failed for opclass %u", opclass);
/* *Determinewhetherarelationcanbeprovenfunctionallydependenton *asetofgroupingcolumns.Ifso,returntrueandaddthepg_constraint *OIDsoftheconstraintsneededfortheprooftothe*constraintDepslist. * *grouping_columnsisalistofgroupingexpressions,inwhichcolumnsof *therelofinterestareVarswiththeindicatedvarno/varlevelsup. * *Currentlyweonlychecktoseeiftherelhasaprimarykeythatisa *subsetofthegrouping_columns.Wecouldalsouseplainuniqueconstraints *ifalltheircolumnsareknownnotnull,butthere'saproblem:weneed *tobeabletorepresentthenot-null-nessaspartoftheconstraintsadded *to*constraintDeps.FIXMEwhenevernot-nullconstraintsgetrepresented *inpg_constraint.
*/ bool
check_functional_grouping(Oid relid,
Index varno, Index varlevelsup,
List *grouping_columns,
List **constraintDeps)
{
Bitmapset *pkattnos;
Bitmapset *groupbyattnos;
Oid constraintOid;
ListCell *gl;
/* If the rel has no PK, then we can't prove functional dependency */
pkattnos = get_primary_key_attnos(relid, false, &constraintOid); if (pkattnos == NULL) returnfalse;
/* Identify all the rel's columns that appear in grouping_columns */
groupbyattnos = NULL;
foreach(gl, grouping_columns)
{
Var *gvar = (Var *) lfirst(gl);
if (bms_is_subset(pkattnos, groupbyattnos))
{ /* The PK is a subset of grouping_columns, so we win */
*constraintDeps = lappend_oid(*constraintDeps, constraintOid); returntrue;
}
returnfalse;
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.31 Sekunden
(vorverarbeitet am 2026-08-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.