Add GetForeignColumnOptions() to foreign.c, and add some documentation.
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 7 Mar 2012 23:20:58 +0000 (18:20 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 7 Mar 2012 23:20:58 +0000 (18:20 -0500)
GetForeignColumnOptions provides some abstraction for accessing
column-specific FDW options, on a par with the access functions that were
already provided here for other FDW-related information.

Adjust file_fdw.c to use GetForeignColumnOptions instead of equivalent
hand-rolled code.

In addition, add some SGML documentation for the functions exported by
foreign.c that are meant for use by FDW authors.

(This is the fdw_helper portion of the proposed pgsql_fdw patch.)

Hanada Shigeru, reviewed by KaiGai Kohei

contrib/file_fdw/file_fdw.c
doc/src/sgml/fdwhandler.sgml
src/backend/foreign/foreign.c
src/include/foreign/foreign.h

index c2faa6235e7666c11c49eaab5e260e0368243913..29f203c6f10eeeed194670aa37956a6190e8e7a1 100644 (file)
@@ -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);
index 12c5f75bfab4ba530923e4f5a6c44d17dbab55aa..dbfcbbc2b36dd49b0f0a8ffc9893da0b2a25a891 100644 (file)
@@ -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>
index c4c2a61d5dcb94edcfe60e6a472b6cd728fdbf13..f27b55a66e4b7aab3ce264ceb0701ba16f8aaaad 100644 (file)
@@ -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
  *
index 191122d08156980b33815658de9a44ee2e01a781..f8aa99e2a45e46f6b09e0f9cf01a7dca6e29e35f 100644 (file)
@@ -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);