mirror of
https://github.com/postgres/postgres.git
synced 2025-07-26 01:22:12 +03:00
Load FK defs into relcache for use by planner
Fastpath ignores this if no triggers defined. Author: Tomas Vondra, with fastpath and comments added by me Reviewers: David Rowley, Simon Riggs
This commit is contained in:
@ -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)
|
||||
{
|
||||
|
Reference in New Issue
Block a user