* RelationGetFKeyList -- get a list of foreign key info for the relation * * Returns a list of ForeignKeyCacheInfo structs, one per FK constraining * the given relation. This data is a direct copy of relevant fields from * pg_constraint. The list items are in no particular order. * * CAUTION: the returned list is part of the relcache's data, and could * vanish in a relcache entry reset.
| 4831 | * modify the list entries anyway, so copying would be a waste of time.) |
| 4832 | */ |
| 4833 | List * |
| 4834 | RelationGetFKeyList(Relation relation) |
| 4835 | { |
| 4836 | List *result; |
| 4837 | Relation conrel; |
| 4838 | SysScanDesc conscan; |
| 4839 | ScanKeyData skey; |
| 4840 | HeapTuple htup; |
| 4841 | List *oldlist; |
| 4842 | MemoryContext oldcxt; |
| 4843 | |
| 4844 | /* Quick exit if we already computed the list. */ |
| 4845 | if (relation->rd_fkeyvalid) |
| 4846 | return relation->rd_fkeylist; |
| 4847 | |
| 4848 | /* Fast path: non-partitioned tables without triggers can't have FKs */ |
| 4849 | if (!relation->rd_rel->relhastriggers && |
| 4850 | relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE) |
| 4851 | return NIL; |
| 4852 | |
| 4853 | /* |
| 4854 | * We build the list we intend to return (in the caller's context) while |
| 4855 | * doing the scan. After successfully completing the scan, we copy that |
| 4856 | * list into the relcache entry. This avoids cache-context memory leakage |
| 4857 | * if we get some sort of error partway through. |
| 4858 | */ |
| 4859 | result = NIL; |
| 4860 | |
| 4861 | /* Prepare to scan pg_constraint for entries having conrelid = this rel. */ |
| 4862 | ScanKeyInit(&skey, |
| 4863 | Anum_pg_constraint_conrelid, |
| 4864 | BTEqualStrategyNumber, F_OIDEQ, |
| 4865 | ObjectIdGetDatum(RelationGetRelid(relation))); |
| 4866 | |
| 4867 | conrel = table_open(ConstraintRelationId, AccessShareLock); |
| 4868 | conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true, |
| 4869 | NULL, 1, &skey); |
| 4870 | |
| 4871 | while (HeapTupleIsValid(htup = systable_getnext(conscan))) |
| 4872 | { |
| 4873 | Form_pg_constraint constraint = (Form_pg_constraint) GETSTRUCT(htup); |
| 4874 | ForeignKeyCacheInfo *info; |
| 4875 | |
| 4876 | /* consider only foreign keys */ |
| 4877 | if (constraint->contype != CONSTRAINT_FOREIGN) |
| 4878 | continue; |
| 4879 | |
| 4880 | info = makeNode(ForeignKeyCacheInfo); |
| 4881 | info->conoid = constraint->oid; |
| 4882 | info->conrelid = constraint->conrelid; |
| 4883 | info->confrelid = constraint->confrelid; |
| 4884 | |
| 4885 | DeconstructFkConstraintRow(htup, &info->nkeys, |
| 4886 | info->conkey, |
| 4887 | info->confkey, |
| 4888 | info->conpfeqop, |
| 4889 | NULL, NULL); |
| 4890 |
no test coverage detected