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>
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>
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
#include <math.h>
+#include "fmgr.h"
#include "nodes/parsenodes.h"
#include "nodes/plannodes.h"
#include "nodes/readfuncs.h"
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
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))
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