diff options
-rw-r--r-- | contrib/file_fdw/file_fdw.c | 49 | ||||
-rw-r--r-- | doc/src/sgml/fdwhandler.sgml | 105 | ||||
-rw-r--r-- | src/backend/foreign/foreign.c | 37 | ||||
-rw-r--r-- | src/include/foreign/foreign.h | 2 |
4 files changed, 154 insertions, 39 deletions
diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c index c2faa6235e7..29f203c6f10 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 12c5f75bfab..dbfcbbc2b36 100644 --- a/doc/src/sgml/fdwhandler.sgml +++ b/doc/src/sgml/fdwhandler.sgml @@ -244,4 +244,109 @@ EndForeignScan (ForeignScanState *node); </sect1> + <sect1 id="fdw-helpers"> + <title>Foreign Data Wrapper Helper Functions</title> + + <para> + 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 + <filename>foreign/foreign.h</filename> in your source file. + That header also defines the struct types that are returned by + these functions. + </para> + + <para> +<programlisting> +ForeignDataWrapper * +GetForeignDataWrapper(Oid fdwid); +</programlisting> + + This function returns a <structname>ForeignDataWrapper</structname> + object for the foreign-data wrapper with the given OID. A + <structname>ForeignDataWrapper</structname> object contains properties + of the FDW (see <filename>foreign/foreign.h</filename> for details). + </para> + + <para> +<programlisting> +ForeignServer * +GetForeignServer(Oid serverid); +</programlisting> + + This function returns a <structname>ForeignServer</structname> object + for the foreign server with the given OID. A + <structname>ForeignServer</structname> object contains properties + of the server (see <filename>foreign/foreign.h</filename> for details). + </para> + + <para> +<programlisting> +UserMapping * +GetUserMapping(Oid userid, Oid serverid); +</programlisting> + + This function returns a <structname>UserMapping</structname> 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 + <literal>PUBLIC</>, or throw error if there is none.) A + <structname>UserMapping</structname> object contains properties of the + user mapping (see <filename>foreign/foreign.h</filename> for details). + </para> + + <para> +<programlisting> +ForeignTable * +GetForeignTable(Oid relid); +</programlisting> + + This function returns a <structname>ForeignTable</structname> object for + the foreign table with the given OID. A + <structname>ForeignTable</structname> object contains properties of the + foreign table (see <filename>foreign/foreign.h</filename> for details). + </para> + + <para> +<programlisting> +List * +GetForeignTableColumnOptions(Oid relid, AttrNumber attnum); +</programlisting> + + 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 + <structname>DefElem</structname>. NIL is returned if the column has no + options. + </para> + + <para> + Some object types have name-based lookup functions in addition to the + OID-based ones: + </para> + + <para> +<programlisting> +ForeignDataWrapper * +GetForeignDataWrapperByName(const char *name, bool missing_ok); +</programlisting> + + This function returns a <structname>ForeignDataWrapper</structname> + 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. + </para> + + <para> +<programlisting> +ForeignServer * +GetForeignServerByName(const char *name, bool missing_ok); +</programlisting> + + This function returns a <structname>ForeignServer</structname> 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. + </para> + + </sect1> + </chapter> diff --git a/src/backend/foreign/foreign.c b/src/backend/foreign/foreign.c index c4c2a61d5dc..f27b55a66e4 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. @@ -248,6 +246,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 191122d0815..f8aa99e2a45 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); |