diff --git a/src/backend/foreign/foreign.c b/src/backend/foreign/foreign.c index 1fdd925..2e9f3f1 100644 --- a/src/backend/foreign/foreign.c +++ b/src/backend/foreign/foreign.c @@ -362,30 +362,6 @@ GetFdwRoutineByRelId(Oid relid) /* - * Determine the relation is a foreign table. - */ -bool -IsForeignTable(Oid relid) -{ - HeapTuple tuple; - Form_pg_class classForm; - char relkind; - - tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); - if (!HeapTupleIsValid(tuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_TABLE), - errmsg("relation with OID %u does not exist", relid))); - classForm = (Form_pg_class) GETSTRUCT(tuple); - relkind = classForm->relkind; - ReleaseSysCache(tuple); - - return (relkind == RELKIND_FOREIGN_TABLE); -} - - - -/* * deflist_to_tuplestore - Helper function to convert DefElem list to * tuplestore usable in SRF. */ diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 6fc6825..b8e4c1f 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -1676,6 +1676,7 @@ _outRelOptInfo(StringInfo str, RelOptInfo *node) WRITE_NODE_FIELD(subplan); WRITE_NODE_FIELD(subrtable); WRITE_NODE_FIELD(subrowmark); + WRITE_BOOL_FIELD(is_foreign_table); WRITE_NODE_FIELD(baserestrictinfo); WRITE_NODE_FIELD(joininfo); WRITE_BOOL_FIELD(has_eclass_joins); diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index ae2e134..780e64c 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -256,7 +256,7 @@ set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte) * least one dimension of cost or sortedness. */ - if (IsForeignTable(rte->relid)) + if (rel->is_foreign_table) { /* only foreign scan path is applyable to foreign table */ add_path(rel, create_foreignscan_path(root, rel)); diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 1d60af8..f86bc5f 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -339,6 +339,13 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, rel->indexlist = indexinfos; + /* + * We should remember whether the relation is a foreign table or not to + * avoid catalog lookup in the phase of path generation. + */ + if (relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE) + rel->is_foreign_table = true; + heap_close(relation, NoLock); /* diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c index b7a5845..7c2a39d 100644 --- a/src/backend/optimizer/util/relnode.c +++ b/src/backend/optimizer/util/relnode.c @@ -85,6 +85,7 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind) rel->subplan = NULL; rel->subrtable = NIL; rel->subrowmark = NIL; + rel->is_foreign_table = false; rel->baserestrictinfo = NIL; rel->baserestrictcost.startup = 0; rel->baserestrictcost.per_tuple = 0; @@ -339,6 +340,7 @@ build_join_rel(PlannerInfo *root, joinrel->subplan = NULL; joinrel->subrtable = NIL; joinrel->subrowmark = NIL; + joinrel->is_foreign_table = false; joinrel->baserestrictinfo = NIL; joinrel->baserestrictcost.startup = 0; joinrel->baserestrictcost.per_tuple = 0; diff --git a/src/include/foreign/foreign.h b/src/include/foreign/foreign.h index fe299b3..b0cb37c 100644 --- a/src/include/foreign/foreign.h +++ b/src/include/foreign/foreign.h @@ -79,6 +79,5 @@ extern Oid GetForeignDataWrapperOidByName(const char *name, bool missing_ok); extern ForeignTable *GetForeignTable(Oid relid); extern FdwRoutine *GetFdwRoutineByRelId(Oid relid); extern FdwRoutine *GetFdwRoutine(Oid fdwhandler); -extern bool IsForeignTable(Oid relid); #endif /* FOREIGN_H */ diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index 133a2bd..5abbb07 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -395,6 +395,7 @@ typedef struct RelOptInfo struct Plan *subplan; /* if subquery */ List *subrtable; /* if subquery */ List *subrowmark; /* if subquery */ + bool is_foreign_table; /* T means relation is a foreign table */ /* used by various scans and joins: */ List *baserestrictinfo; /* RestrictInfo structures (if base