diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c index c2faa6235e..29f203c6f1 100644 --- a/contrib/file_fdw/file_fdw.c +++ b/contrib/file_fdw/file_fdw.c @@ -27,7 +27,6 @@ #include "optimizer/cost.h" #include "optimizer/pathnode.h" #include "utils/rel.h" -#include "utils/syscache.h" PG_MODULE_MAGIC; @@ -346,54 +345,30 @@ get_file_fdw_attribute_options(Oid relid) /* Retrieve FDW options for all user-defined attributes. */ for (attnum = 1; attnum <= natts; attnum++) { - HeapTuple tuple; - Form_pg_attribute attr; - Datum datum; - bool isnull; + Form_pg_attribute attr = tupleDesc->attrs[attnum - 1]; + List *options; + ListCell *lc; /* Skip dropped attributes. */ - if (tupleDesc->attrs[attnum - 1]->attisdropped) + if (attr->attisdropped) continue; - /* - * We need the whole pg_attribute tuple not just what is in the - * tupleDesc, so must do a catalog lookup. - */ - tuple = SearchSysCache2(ATTNUM, - RelationGetRelid(rel), - Int16GetDatum(attnum)); - if (!HeapTupleIsValid(tuple)) - elog(ERROR, "cache lookup failed for attribute %d of relation %u", - attnum, RelationGetRelid(rel)); - attr = (Form_pg_attribute) GETSTRUCT(tuple); - - datum = SysCacheGetAttr(ATTNUM, - tuple, - Anum_pg_attribute_attfdwoptions, - &isnull); - if (!isnull) + options = GetForeignColumnOptions(relid, attnum); + foreach(lc, options) { - List *options = untransformRelOptions(datum); - ListCell *lc; + DefElem *def = (DefElem *) lfirst(lc); - foreach(lc, options) + if (strcmp(def->defname, "force_not_null") == 0) { - DefElem *def = (DefElem *) lfirst(lc); - - if (strcmp(def->defname, "force_not_null") == 0) + if (defGetBoolean(def)) { - if (defGetBoolean(def)) - { - char *attname = pstrdup(NameStr(attr->attname)); + char *attname = pstrdup(NameStr(attr->attname)); - fnncolumns = lappend(fnncolumns, makeString(attname)); - } + fnncolumns = lappend(fnncolumns, makeString(attname)); } - /* maybe in future handle other options here */ } + /* maybe in future handle other options here */ } - - ReleaseSysCache(tuple); } heap_close(rel, AccessShareLock); diff --git a/doc/src/sgml/fdwhandler.sgml b/doc/src/sgml/fdwhandler.sgml index 12c5f75bfa..dbfcbbc2b3 100644 --- a/doc/src/sgml/fdwhandler.sgml +++ b/doc/src/sgml/fdwhandler.sgml @@ -244,4 +244,109 @@ EndForeignScan (ForeignScanState *node); + + Foreign Data Wrapper Helper Functions + + + Several helper functions are exported from the core server so that + authors of foreign data wrappers can get easy access to attributes of + FDW-related objects, such as FDW options. + To use any of these functions, you need to include the header file + foreign/foreign.h in your source file. + That header also defines the struct types that are returned by + these functions. + + + + +ForeignDataWrapper * +GetForeignDataWrapper(Oid fdwid); + + + This function returns a ForeignDataWrapper + object for the foreign-data wrapper with the given OID. A + ForeignDataWrapper object contains properties + of the FDW (see foreign/foreign.h for details). + + + + +ForeignServer * +GetForeignServer(Oid serverid); + + + This function returns a ForeignServer object + for the foreign server with the given OID. A + ForeignServer object contains properties + of the server (see foreign/foreign.h for details). + + + + +UserMapping * +GetUserMapping(Oid userid, Oid serverid); + + + This function returns a UserMapping object for + the user mapping of the given role on the given server. (If there is no + mapping for the specific user, it will return the mapping for + PUBLIC, or throw error if there is none.) A + UserMapping object contains properties of the + user mapping (see foreign/foreign.h for details). + + + + +ForeignTable * +GetForeignTable(Oid relid); + + + This function returns a ForeignTable object for + the foreign table with the given OID. A + ForeignTable object contains properties of the + foreign table (see foreign/foreign.h for details). + + + + +List * +GetForeignTableColumnOptions(Oid relid, AttrNumber attnum); + + + This function returns the per-column FDW options for the column with the + given foreign table OID and attribute number, in the form of a list of + DefElem. NIL is returned if the column has no + options. + + + + Some object types have name-based lookup functions in addition to the + OID-based ones: + + + + +ForeignDataWrapper * +GetForeignDataWrapperByName(const char *name, bool missing_ok); + + + This function returns a ForeignDataWrapper + object for the foreign-data wrapper with the given name. If the wrapper + is not found, return NULL if missing_ok is true, otherwise raise an + error. + + + + +ForeignServer * +GetForeignServerByName(const char *name, bool missing_ok); + + + This function returns a ForeignServer object + for the foreign server with the given name. If the server is not found, + return NULL if missing_ok is true, otherwise raise an error. + + + + diff --git a/src/backend/foreign/foreign.c b/src/backend/foreign/foreign.c index c4c2a61d5d..f27b55a66e 100644 --- a/src/backend/foreign/foreign.c +++ b/src/backend/foreign/foreign.c @@ -28,7 +28,6 @@ extern Datum pg_options_to_table(PG_FUNCTION_ARGS); extern Datum postgresql_fdw_validator(PG_FUNCTION_ARGS); - /* * GetForeignDataWrapper - look up the foreign-data wrapper by OID. */ @@ -71,7 +70,6 @@ GetForeignDataWrapper(Oid fdwid) } - /* * GetForeignDataWrapperByName - look up the foreign-data wrapper * definition by name. @@ -247,6 +245,39 @@ GetForeignTable(Oid relid) } +/* + * GetForeignColumnOptions - Get attfdwoptions of given relation/attnum + * as list of DefElem. + */ +List * +GetForeignColumnOptions(Oid relid, AttrNumber attnum) +{ + List *options; + HeapTuple tp; + Datum datum; + bool isnull; + + tp = SearchSysCache2(ATTNUM, + ObjectIdGetDatum(relid), + Int16GetDatum(attnum)); + if (!HeapTupleIsValid(tp)) + elog(ERROR, "cache lookup failed for attribute %d of relation %u", + attnum, relid); + datum = SysCacheGetAttr(ATTNUM, + tp, + Anum_pg_attribute_attfdwoptions, + &isnull); + if (isnull) + options = NIL; + else + options = untransformRelOptions(datum); + + ReleaseSysCache(tp); + + return options; +} + + /* * GetFdwRoutine - call the specified foreign-data wrapper handler routine * to get its FdwRoutine struct. @@ -498,6 +529,7 @@ postgresql_fdw_validator(PG_FUNCTION_ARGS) PG_RETURN_BOOL(true); } + /* * get_foreign_data_wrapper_oid - given a FDW name, look up the OID * @@ -518,6 +550,7 @@ get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok) return oid; } + /* * get_foreign_server_oid - given a FDW name, look up the OID * diff --git a/src/include/foreign/foreign.h b/src/include/foreign/foreign.h index 191122d081..f8aa99e2a4 100644 --- a/src/include/foreign/foreign.h +++ b/src/include/foreign/foreign.h @@ -76,6 +76,8 @@ extern ForeignDataWrapper *GetForeignDataWrapperByName(const char *name, bool missing_ok); extern ForeignTable *GetForeignTable(Oid relid); +extern List *GetForeignColumnOptions(Oid relid, AttrNumber attnum); + extern Oid get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok); extern Oid get_foreign_server_oid(const char *servername, bool missing_ok);