doc/src/sgml/custom-scan.sgml | 16 +++------------- src/backend/nodes/outfuncs.c | 7 ++++--- src/backend/nodes/readfuncs.c | 41 +++++++++++++++++++++++++++++++++++++++++ src/include/nodes/plannodes.h | 5 ++--- 4 files changed, 50 insertions(+), 19 deletions(-) diff --git a/doc/src/sgml/custom-scan.sgml b/doc/src/sgml/custom-scan.sgml index a229326..d042adb 100644 --- a/doc/src/sgml/custom-scan.sgml +++ b/doc/src/sgml/custom-scan.sgml @@ -83,7 +83,9 @@ typedef struct CustomPath 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. + detailed below. Also note that this field shall be serialized using + a pair of library name and symbol name, thus, method variable has to + be resolvable by linker. @@ -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. - diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 3e75cd1..af6674c 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -612,10 +612,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->methodsLibraryName); + appendStringInfoChar(str, ' '); + _outToken(str, node->methods->methodsSymbolName); } static void diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 94ba6dc..d143dac 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -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) } /* + * _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); /* methodsLibraryName */ + library_name = nullable_string(token, length); + token = pg_strtok(&length); /* methodsSymbolName */ + symbol_name = nullable_string(token, length); + + methods = (const CustomScanMethods *) + load_external_function(library_name, symbol_name, true, NULL); + Assert(strcmp(methods->methodsLibraryName, library_name) == 0 && + strcmp(methods->methodsSymbolName, symbol_name) == 0); + local_node->methods = methods; + + READ_DONE(); +} + +/* * ReadCommonJoin * Assign the basic stuff of all nodes that inherit from Join */ @@ -2361,6 +2400,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 6b28c8e..5ecc2d1 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -552,12 +552,11 @@ struct CustomScan; typedef struct CustomScanMethods { const char *CustomName; + const char *methodsLibraryName; + const char *methodsSymbolName; /* 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