]> granicus.if.org Git - postgresql/commitdiff
Provide readfuncs support for custom scans.
authorRobert Haas <rhaas@postgresql.org>
Thu, 12 Nov 2015 12:40:31 +0000 (07:40 -0500)
committerRobert Haas <rhaas@postgresql.org>
Thu, 12 Nov 2015 12:40:31 +0000 (07:40 -0500)
Commit a0d9f6e434bb56f7e5441b7988f3982feead33b3 added this support for
all other plan node types; this fills in the gap.

Since TextOutCustomScan complicates this and is pretty well useless,
remove it.

KaiGai Kohei, with some modifications by me.

doc/src/sgml/custom-scan.sgml
src/backend/nodes/outfuncs.c
src/backend/nodes/readfuncs.c
src/include/nodes/plannodes.h

index a229326836a7b46bdb141192484c1da13d9e53cf..5bba1256d3199f01be999da4fff74eda6d56bba2 100644 (file)
@@ -82,8 +82,10 @@ typedef struct CustomPath
     by <literal>nodeToString</>, so that debugging routines that attempt to
     print the custom path will work as designed.  <structfield>methods</> must
     point to a (usually statically allocated) object implementing the required
-    custom path methods, of which there are currently only two, as further
-    detailed below.
+    custom path methods, of which there is currently only one.  The
+    <structfield>LibraryName</> and <structfield>SymbolName</> fields must also
+    be initialized so that the dynamic loader can resolve them to locate the
+    method table.
   </para>
 
   <para>
@@ -218,18 +220,6 @@ Node *(*CreateCustomScanState) (CustomScan *cscan);
     the <function>BeginCustomScan</> callback will be invoked to give the
     custom scan provider a chance to do whatever else is needed.
    </para>
-
-   <para>
-<programlisting>
-void (*TextOutCustomScan) (StringInfo str,
-                           const CustomScan *node);
-</programlisting>
-    Generate additional output when <function>nodeToString</> is invoked on
-    this custom plan node.  This callback is optional.  Since
-    <function>nodeToString</> will automatically dump all fields in the
-    structure, including the substructure of the <quote>custom</> fields,
-    there is usually not much need for this callback.
-   </para>
   </sect2>
  </sect1>
 
index c230ee8296c4609344b4311602d0889593a2f020..012c14bf29af37ff48897edbc85a0cb79f1db1a7 100644 (file)
@@ -613,10 +613,11 @@ _outCustomScan(StringInfo str, const CustomScan *node)
        WRITE_NODE_FIELD(custom_private);
        WRITE_NODE_FIELD(custom_scan_tlist);
        WRITE_BITMAPSET_FIELD(custom_relids);
+       /* Dump library and symbol name instead of raw pointer */
        appendStringInfoString(str, " :methods ");
-       _outToken(str, node->methods->CustomName);
-       if (node->methods->TextOutCustomScan)
-               node->methods->TextOutCustomScan(str, node);
+       _outToken(str, node->methods->LibraryName);
+       appendStringInfoChar(str, ' ');
+       _outToken(str, node->methods->SymbolName);
 }
 
 static void
index 5e258c939f2c484d7f1579478da175a62cd65c9e..222e2ed31080e3e2674e0fd30686d2cf6fc0bc2a 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <math.h>
 
+#include "fmgr.h"
 #include "nodes/parsenodes.h"
 #include "nodes/plannodes.h"
 #include "nodes/readfuncs.h"
@@ -1806,6 +1807,44 @@ _readForeignScan(void)
        READ_DONE();
 }
 
+/*
+ * _readCustomScan
+ */
+static CustomScan *
+_readCustomScan(void)
+{
+       READ_LOCALS(CustomScan);
+       char       *library_name;
+       char       *symbol_name;
+       const CustomScanMethods *methods;
+
+       ReadCommonScan(&local_node->scan);
+
+       READ_UINT_FIELD(flags);
+       READ_NODE_FIELD(custom_plans);
+       READ_NODE_FIELD(custom_exprs);
+       READ_NODE_FIELD(custom_private);
+       READ_NODE_FIELD(custom_scan_tlist);
+       READ_BITMAPSET_FIELD(custom_relids);
+
+       /*
+        * Reconstruction of methods using library and symbol name
+        */
+       token = pg_strtok(&length);             /* skip methods: */
+       token = pg_strtok(&length);             /* LibraryName */
+       library_name = nullable_string(token, length);
+       token = pg_strtok(&length);             /* SymbolName */
+       symbol_name = nullable_string(token, length);
+
+       methods = (const CustomScanMethods *)
+               load_external_function(library_name, symbol_name, true, NULL);
+       Assert(strcmp(methods->LibraryName, library_name) == 0 &&
+                  strcmp(methods->SymbolName, symbol_name) == 0);
+       local_node->methods = methods;
+
+       READ_DONE();
+}
+
 /*
  * ReadCommonJoin
  *     Assign the basic stuff of all nodes that inherit from Join
@@ -2362,6 +2401,8 @@ parseNodeString(void)
                return_value = _readWorkTableScan();
        else if (MATCH("FOREIGNSCAN", 11))
                return_value = _readForeignScan();
+       else if (MATCH("CUSTOMSCAN", 10))
+               return_value = _readCustomScan();
        else if (MATCH("JOIN", 4))
                return_value = _readJoin();
        else if (MATCH("NESTLOOP", 8))
index 292219db51f541de86b352077ccdb75185778ed1..37086c65903bc11915e760483ff639d897e62ca7 100644 (file)
@@ -557,12 +557,11 @@ struct CustomScan;
 typedef struct CustomScanMethods
 {
        const char *CustomName;
+       const char *LibraryName;
+       const char *SymbolName;
 
        /* Create execution state (CustomScanState) from a CustomScan plan node */
        Node       *(*CreateCustomScanState) (struct CustomScan *cscan);
-       /* Optional: print custom_xxx fields in some special way */
-       void            (*TextOutCustomScan) (StringInfo str,
-                                                                                         const struct CustomScan *node);
 } CustomScanMethods;
 
 typedef struct CustomScan