diff options
author | Robert Haas <rhaas@postgresql.org> | 2016-03-29 11:00:18 -0400 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2016-03-29 11:28:04 -0400 |
commit | f9143d102ffd0947ca904c62b1d3d6fd587e0c80 (patch) | |
tree | e75fb310cbad87d2641291fec320302531f5c548 /src/backend/nodes | |
parent | 534da37927f97ae7cb1b468963ba9bca747209ea (diff) | |
download | postgresql-f9143d102ffd0947ca904c62b1d3d6fd587e0c80.tar.gz postgresql-f9143d102ffd0947ca904c62b1d3d6fd587e0c80.zip |
Rework custom scans to work more like the new extensible node stuff.
Per discussion, the new extensible node framework is thought to be
better designed than the custom path/scan/scanstate stuff we added
in PostgreSQL 9.5. Rework the latter to be more like the former.
This is not backward-compatible, but we generally don't promise that
for C APIs, and there probably aren't many people using this yet
anyway.
KaiGai Kohei, reviewed by Petr Jelinek and me. Some further
cosmetic changes by me.
Diffstat (limited to 'src/backend/nodes')
-rw-r--r-- | src/backend/nodes/extensible.c | 88 | ||||
-rw-r--r-- | src/backend/nodes/outfuncs.c | 6 | ||||
-rw-r--r-- | src/backend/nodes/readfuncs.c | 19 |
3 files changed, 76 insertions, 37 deletions
diff --git a/src/backend/nodes/extensible.c b/src/backend/nodes/extensible.c index 2473b658b17..d61be58c45d 100644 --- a/src/backend/nodes/extensible.c +++ b/src/backend/nodes/extensible.c @@ -24,61 +24,87 @@ #include "utils/hsearch.h" static HTAB *extensible_node_methods = NULL; +static HTAB *custom_scan_methods = NULL; typedef struct { char extnodename[EXTNODENAME_MAX_LEN]; - const ExtensibleNodeMethods *methods; + const void *extnodemethods; } ExtensibleNodeEntry; /* - * Register a new type of extensible node. + * An internal function to register a new callback structure */ -void -RegisterExtensibleNodeMethods(const ExtensibleNodeMethods *methods) +static void +RegisterExtensibleNodeEntry(HTAB **p_htable, const char *htable_label, + const char *extnodename, + const void *extnodemethods) { ExtensibleNodeEntry *entry; bool found; - if (extensible_node_methods == NULL) + if (*p_htable == NULL) { HASHCTL ctl; memset(&ctl, 0, sizeof(HASHCTL)); ctl.keysize = EXTNODENAME_MAX_LEN; ctl.entrysize = sizeof(ExtensibleNodeEntry); - extensible_node_methods = hash_create("Extensible Node Methods", - 100, &ctl, HASH_ELEM); + + *p_htable = hash_create(htable_label, 100, &ctl, HASH_ELEM); } - if (strlen(methods->extnodename) >= EXTNODENAME_MAX_LEN) + if (strlen(extnodename) >= EXTNODENAME_MAX_LEN) elog(ERROR, "extensible node name is too long"); - entry = (ExtensibleNodeEntry *) hash_search(extensible_node_methods, - methods->extnodename, + entry = (ExtensibleNodeEntry *) hash_search(*p_htable, + extnodename, HASH_ENTER, &found); if (found) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("extensible node type \"%s\" already exists", - methods->extnodename))); + extnodename))); - entry->methods = methods; + entry->extnodemethods = extnodemethods; } /* - * Get the methods for a given type of extensible node. + * Register a new type of extensible node. */ -const ExtensibleNodeMethods * -GetExtensibleNodeMethods(const char *extnodename, bool missing_ok) +void +RegisterExtensibleNodeMethods(const ExtensibleNodeMethods *methods) +{ + RegisterExtensibleNodeEntry(&extensible_node_methods, + "Extensible Node Methods", + methods->extnodename, + methods); +} + +/* + * Register a new type of custom scan node + */ +void +RegisterCustomScanMethods(const CustomScanMethods *methods) +{ + RegisterExtensibleNodeEntry(&custom_scan_methods, + "Custom Scan Methods", + methods->CustomName, + methods); +} + +/* + * An internal routine to get an ExtensibleNodeEntry by the given identifier + */ +static const void * +GetExtensibleNodeEntry(HTAB *htable, const char *extnodename, bool missing_ok) { ExtensibleNodeEntry *entry = NULL; - if (extensible_node_methods != NULL) - entry = (ExtensibleNodeEntry *) hash_search(extensible_node_methods, + if (htable != NULL) + entry = (ExtensibleNodeEntry *) hash_search(htable, extnodename, HASH_FIND, NULL); - if (!entry) { if (missing_ok) @@ -89,5 +115,29 @@ GetExtensibleNodeMethods(const char *extnodename, bool missing_ok) extnodename))); } - return entry->methods; + return entry->extnodemethods; +} + +/* + * Get the methods for a given type of extensible node. + */ +const ExtensibleNodeMethods * +GetExtensibleNodeMethods(const char *extnodename, bool missing_ok) +{ + return (const ExtensibleNodeMethods *) + GetExtensibleNodeEntry(extensible_node_methods, + extnodename, + missing_ok); +} + +/* + * Get the methods for a given name of CustomScanMethods + */ +const CustomScanMethods * +GetCustomScanMethods(const char *CustomName, bool missing_ok) +{ + return (const CustomScanMethods *) + GetExtensibleNodeEntry(custom_scan_methods, + CustomName, + missing_ok); } diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 32d03f7f257..83abaa68a38 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -632,11 +632,9 @@ _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 */ + /* CustomName is a key to lookup CustomScanMethods */ appendStringInfoString(str, " :methods "); - _outToken(str, node->methods->LibraryName); - appendStringInfoChar(str, ' '); - _outToken(str, node->methods->SymbolName); + _outToken(str, node->methods->CustomName); } static void diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 6db0492e152..cb0752a6ad8 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -1827,8 +1827,7 @@ static CustomScan * _readCustomScan(void) { READ_LOCALS(CustomScan); - char *library_name; - char *symbol_name; + char *custom_name; const CustomScanMethods *methods; ReadCommonScan(&local_node->scan); @@ -1840,19 +1839,11 @@ _readCustomScan(void) READ_NODE_FIELD(custom_scan_tlist); READ_BITMAPSET_FIELD(custom_relids); - /* - * Reconstruction of methods using library and symbol name - */ + /* Lookup CustomScanMethods by CustomName */ 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); + token = pg_strtok(&length); /* CustomName */ + custom_name = nullable_string(token, length); + methods = GetCustomScanMethods(custom_name, false); local_node->methods = methods; READ_DONE(); |