aboutsummaryrefslogtreecommitdiff
path: root/src/backend/nodes
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2016-03-29 11:00:18 -0400
committerRobert Haas <rhaas@postgresql.org>2016-03-29 11:28:04 -0400
commitf9143d102ffd0947ca904c62b1d3d6fd587e0c80 (patch)
treee75fb310cbad87d2641291fec320302531f5c548 /src/backend/nodes
parent534da37927f97ae7cb1b468963ba9bca747209ea (diff)
downloadpostgresql-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.c88
-rw-r--r--src/backend/nodes/outfuncs.c6
-rw-r--r--src/backend/nodes/readfuncs.c19
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();