Provide readfuncs support for custom scans.
authorRobert Haas
Thu, 12 Nov 2015 12:40:31 +0000 (07:40 -0500)
committerRobert Haas
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 nodeToString, so that debugging routines that attempt to
     print the custom path will work as designed.  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
+    LibraryName and SymbolName fields must also
+    be initialized so that the dynamic loader can resolve them to locate the
+    method table.
   
 
   
@@ -218,18 +220,6 @@ Node *(*CreateCustomScanState) (CustomScan *cscan);
     the BeginCustomScan callback will be invoked to give the
     custom scan provider a chance to do whatever else is needed.
    
-
-   
-
-void (*TextOutCustomScan) (StringInfo str,
-                           const CustomScan *node);
-
-    Generate additional output when nodeToString is invoked on
-    this custom plan node.  This callback is optional.  Since
-    nodeToString will automatically dump all fields in the
-    structure, including the substructure of the custom fields,
-    there is usually not much need for this callback.
-   
   
  
 
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 
 
+#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