diff options
Diffstat (limited to 'src/backend/optimizer/util/plancat.c')
-rw-r--r-- | src/backend/optimizer/util/plancat.c | 85 |
1 files changed, 84 insertions, 1 deletions
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 5bdeac0df64..0f291275dcc 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -28,6 +28,7 @@ #include "catalog/dependency.h" #include "catalog/heap.h" #include "catalog/pg_am.h" +#include "catalog/pg_constraint.h" #include "foreign/fdwapi.h" #include "miscadmin.h" #include "nodes/makefuncs.h" @@ -41,6 +42,7 @@ #include "rewrite/rewriteManip.h" #include "storage/bufmgr.h" #include "utils/lsyscache.h" +#include "utils/syscache.h" #include "utils/rel.h" #include "utils/snapmgr.h" @@ -94,6 +96,9 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + List *fkinfos = NIL; + List *fkoidlist; + ListCell *l; /* * We need not lock the relation since it was already locked, either by @@ -141,7 +146,6 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (hasindex) { List *indexoidlist; - ListCell *l; LOCKMODE lmode; indexoidlist = RelationGetIndexList(relation); @@ -388,6 +392,85 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, rel->indexlist = indexinfos; + /* + * Load foreign key data. Note this is the definitional data from the + * catalog only and does not lock the referenced tables here. The + * precise definition of the FK is important and may affect the usage + * elsewhere in the planner, e.g. if the constraint is deferred or + * if the constraint is not valid then relying upon this in the executor + * may not be accurate, though might be considered a useful estimate for + * planning purposes. + */ + fkoidlist = RelationGetFKeyList(relation); + + foreach(l, fkoidlist) + { + int i; + ArrayType *arr; + Datum adatum; + bool isnull; + int numkeys; + Oid fkoid = lfirst_oid(l); + + HeapTuple htup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(fkoid)); + Form_pg_constraint constraint = (Form_pg_constraint) GETSTRUCT(htup); + + ForeignKeyOptInfo *info; + + Assert(constraint->contype == CONSTRAINT_FOREIGN); + + info = makeNode(ForeignKeyOptInfo); + + info->conrelid = constraint->conrelid; + info->confrelid = constraint->confrelid; + + /* conkey */ + adatum = SysCacheGetAttr(CONSTROID, htup, + Anum_pg_constraint_conkey, &isnull); + Assert(!isnull); + + arr = DatumGetArrayTypeP(adatum); + numkeys = ARR_DIMS(arr)[0]; + info->conkeys = (int*)palloc0(numkeys * sizeof(int)); + + for (i = 0; i < numkeys; i++) + info->conkeys[i] = ((int16 *) ARR_DATA_PTR(arr))[i]; + + /* confkey */ + adatum = SysCacheGetAttr(CONSTROID, htup, + Anum_pg_constraint_confkey, &isnull); + Assert(!isnull); + + arr = DatumGetArrayTypeP(adatum); + numkeys = ARR_DIMS(arr)[0]; + info->confkeys = (int*)palloc0(numkeys * sizeof(int)); + + for (i = 0; i < numkeys; i++) + info->confkeys[i] = ((int16 *) ARR_DATA_PTR(arr))[i]; + + /* conpfeqop */ + adatum = SysCacheGetAttr(CONSTROID, htup, + Anum_pg_constraint_conpfeqop, &isnull); + Assert(!isnull); + + arr = DatumGetArrayTypeP(adatum); + numkeys = ARR_DIMS(arr)[0]; + info->conpfeqop = (Oid*)palloc0(numkeys * sizeof(Oid)); + + for (i = 0; i < numkeys; i++) + info->conpfeqop[i] = ((Oid *) ARR_DATA_PTR(arr))[i]; + + info->nkeys = numkeys; + + ReleaseSysCache(htup); + + fkinfos = lcons(info, fkinfos); + } + + list_free(fkoidlist); + + rel->fkeylist = fkinfos; + /* Grab foreign-table info using the relcache, while we have it */ if (relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE) { |