From: Robert Haas Date: Thu, 12 Nov 2015 12:40:31 +0000 (-0500) Subject: Provide readfuncs support for custom scans. X-Git-Tag: REL9_6_BETA1~1106 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a05dc4d7fd57d4ae084c1f0801973e5c1a1aa26e;p=postgresql Provide readfuncs support for custom scans. 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. --- diff --git a/doc/src/sgml/custom-scan.sgml b/doc/src/sgml/custom-scan.sgml index a229326836..5bba1256d3 100644 --- a/doc/src/sgml/custom-scan.sgml +++ b/doc/src/sgml/custom-scan.sgml @@ -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. - diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index c230ee8296..012c14bf29 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 5e258c939f..222e2ed310 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) 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 292219db51..37086c6590 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