diff --git a/doc/src/sgml/custom-scan.sgml b/doc/src/sgml/custom-scan.sgml index a229326836a7b46bdb141192484c1da13d9e53cf..5bba1256d3199f01be999da4fff74eda6d56bba2 100644 --- a/doc/src/sgml/custom-scan.sgml +++ b/doc/src/sgml/custom-scan.sgml @@ -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> diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index c230ee8296c4609344b4311602d0889593a2f020..012c14bf29af37ff48897edbc85a0cb79f1db1a7 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -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 diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 5e258c939f2c484d7f1579478da175a62cd65c9e..222e2ed31080e3e2674e0fd30686d2cf6fc0bc2a 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -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)) diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 292219db51f541de86b352077ccdb75185778ed1..37086c65903bc11915e760483ff639d897e62ca7 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -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