diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c index c2faa62..0193aae 100644 *** a/contrib/file_fdw/file_fdw.c --- b/contrib/file_fdw/file_fdw.c *************** *** 27,33 **** #include "optimizer/cost.h" #include "optimizer/pathnode.h" #include "utils/rel.h" ! #include "utils/syscache.h" PG_MODULE_MAGIC; --- 27,33 ---- #include "optimizer/cost.h" #include "optimizer/pathnode.h" #include "utils/rel.h" ! #include "utils/lsyscache.h" PG_MODULE_MAGIC; *************** get_file_fdw_attribute_options(Oid relid *** 346,399 **** /* Retrieve FDW options for all user-defined attributes. */ for (attnum = 1; attnum <= natts; attnum++) { ! HeapTuple tuple; ! Form_pg_attribute attr; ! Datum datum; ! bool isnull; /* Skip dropped attributes. */ if (tupleDesc->attrs[attnum - 1]->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) { ! List *options = untransformRelOptions(datum); ! ListCell *lc; ! foreach(lc, options) { ! DefElem *def = (DefElem *) lfirst(lc); ! ! if (strcmp(def->defname, "force_not_null") == 0) { ! if (defGetBoolean(def)) ! { ! char *attname = pstrdup(NameStr(attr->attname)); ! fnncolumns = lappend(fnncolumns, makeString(attname)); ! } } - /* maybe in future handle other options here */ } } - - ReleaseSysCache(tuple); } heap_close(rel, AccessShareLock); --- 346,374 ---- /* Retrieve FDW options for all user-defined attributes. */ for (attnum = 1; attnum <= natts; attnum++) { ! List *options; ! ListCell *lc; /* Skip dropped attributes. */ if (tupleDesc->attrs[attnum - 1]->attisdropped) continue; ! options = GetForeignColumnOptions(relid, attnum); ! foreach(lc, options) { ! DefElem *def = (DefElem *) lfirst(lc); ! if (strcmp(def->defname, "force_not_null") == 0) { ! if (defGetBoolean(def)) { ! char *attname = pstrdup(get_attname(relid, attnum)); ! fnncolumns = lappend(fnncolumns, makeString(attname)); } } + /* maybe in future handle other options here */ } } heap_close(rel, AccessShareLock); diff --git a/doc/src/sgml/fdwhandler.sgml b/doc/src/sgml/fdwhandler.sgml index 12c5f75..7900484 100644 *** a/doc/src/sgml/fdwhandler.sgml --- b/doc/src/sgml/fdwhandler.sgml *************** EndForeignScan (ForeignScanState *node); *** 244,247 **** --- 244,352 ---- + + Foreign Data Wrapper Helper Functions + + + Several helper functions are exported from core so that authors of FDW + can get easy access to attributes of FDW-related objects such as FDW + options. + + + + + ForeignDataWrapper * + GetForeignDataWrapper(Oid fdwid); + + + This function returns a ForeignDataWrapper object + for a foreign-data wrapper with given oid. A + ForeignDataWrapper object contains oid of the + wrapper itself, oid of the owner of the wrapper, name of the wrapper, oid + of fdwhandler function, oid of fdwvalidator function, and FDW options in + the form of list of DefElem. + + + + + ForeignServer * + GetForeignServer(Oid serverid); + + + This function returns a ForeignServer object for + a foreign server with given oid. A ForeignServer + object contains oid of the server, oid of the wrapper for the server, oid + of the owner of the server, name of the server, type of the server, + version of the server, and FDW options in the form of list of + DefElem. + + + + + UserMapping * + GetUserMapping(Oid userid, Oid serverid); + + + This function returns a UserMapping object for a + user mapping with given oid pair. A UserMapping + object contains oid of the user, oid of the server, and FDW options in the + form of list of DefElem. + + + + + ForeignTable * + GetForeignTable(Oid relid); + + + This function returns a ForeignTable object for a + foreign table with given oid. A ForeignTable + object contains oid of the foreign table, oid of the server for the table, + and FDW options in the form of list of DefElem. + + + + + List * + GetForeignTableColumnOptions(Oid relid, AttrNumber attnum); + + + This function returns per-column FDW options for a column with given + relation oid and attribute number in the form of list of + DefElem. + + + + Some object types have name-based functions. + + + + + ForeignDataWrapper * + GetForeignDataWrapperByName(const char *name, bool missing_ok); + + + This function returns a ForeignDataWrapper object + for a foreign-data wrapper with given name. If the wrapper is not found, + return NULL if missing_ok was true, otherwise raise an error. + + + + + ForeignServer * + GetForeignServerByName(const char *name, bool missing_ok); + + + This function returns a ForeignServer object for + a foreign server with given name. If the server is not found, return NULL + if missing_ok was true, otherwise raise an error. + + + + To use any of these functions, you need to include + foreign/foreign.h in your source file. + + + + diff --git a/src/backend/foreign/foreign.c b/src/backend/foreign/foreign.c index c4c2a61..4db26b5 100644 *** a/src/backend/foreign/foreign.c --- b/src/backend/foreign/foreign.c *************** *** 17,22 **** --- 17,23 ---- #include "catalog/pg_foreign_server.h" #include "catalog/pg_foreign_table.h" #include "catalog/pg_user_mapping.h" + #include "commands/defrem.h" #include "foreign/fdwapi.h" #include "foreign/foreign.h" #include "miscadmin.h" *************** GetForeignTable(Oid relid) *** 246,251 **** --- 247,282 ---- return ft; } + /* + * 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 diff --git a/src/include/foreign/foreign.h b/src/include/foreign/foreign.h index 191122d..4a4ce23 100644 *** a/src/include/foreign/foreign.h --- b/src/include/foreign/foreign.h *************** extern ForeignDataWrapper *GetForeignDat *** 75,80 **** --- 75,81 ---- 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);