Provide readfuncs support for custom scans.

Commit a0d9f6e434 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.
This commit is contained in:
Robert Haas 2015-11-12 07:40:31 -05:00
parent 39b9978d9c
commit a05dc4d7fd
4 changed files with 51 additions and 20 deletions

View 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>

View 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

View 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))

View 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