aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/commands/explain.c1
-rw-r--r--src/backend/nodes/extensible.c88
-rw-r--r--src/backend/nodes/outfuncs.c6
-rw-r--r--src/backend/nodes/readfuncs.c19
-rw-r--r--src/backend/optimizer/plan/createplan.c1
-rw-r--r--src/include/executor/nodeCustom.h1
-rw-r--r--src/include/nodes/execnodes.h35
-rw-r--r--src/include/nodes/extensible.h85
-rw-r--r--src/include/nodes/plannodes.h14
-rw-r--r--src/include/nodes/relation.h19
10 files changed, 168 insertions, 101 deletions
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 787b0b93cce..09c230468bb 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -21,6 +21,7 @@
#include "commands/prepare.h"
#include "executor/hashjoin.h"
#include "foreign/fdwapi.h"
+#include "nodes/extensible.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/planmain.h"
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();
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index d159a17fd26..e4bc14a1510 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -24,6 +24,7 @@
#include "catalog/pg_class.h"
#include "foreign/fdwapi.h"
#include "miscadmin.h"
+#include "nodes/extensible.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
diff --git a/src/include/executor/nodeCustom.h b/src/include/executor/nodeCustom.h
index 410a3ad14db..9d0b3935288 100644
--- a/src/include/executor/nodeCustom.h
+++ b/src/include/executor/nodeCustom.h
@@ -14,6 +14,7 @@
#include "access/parallel.h"
#include "nodes/execnodes.h"
+#include "nodes/extensible.h"
/*
* General executor code
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 0113e5c663c..bf2a09bc39c 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1606,38 +1606,7 @@ typedef struct ForeignScanState
* the BeginCustomScan method.
* ----------------
*/
-struct ParallelContext; /* avoid including parallel.h here */
-struct shm_toc; /* avoid including shm_toc.h here */
-struct ExplainState; /* avoid including explain.h here */
-struct CustomScanState;
-
-typedef struct CustomExecMethods
-{
- const char *CustomName;
-
- /* Executor methods: mark/restore are optional, the rest are required */
- void (*BeginCustomScan) (struct CustomScanState *node,
- EState *estate,
- int eflags);
- TupleTableSlot *(*ExecCustomScan) (struct CustomScanState *node);
- void (*EndCustomScan) (struct CustomScanState *node);
- void (*ReScanCustomScan) (struct CustomScanState *node);
- void (*MarkPosCustomScan) (struct CustomScanState *node);
- void (*RestrPosCustomScan) (struct CustomScanState *node);
- /* Optional: parallel execution support */
- Size (*EstimateDSMCustomScan) (struct CustomScanState *node,
- struct ParallelContext *pcxt);
- void (*InitializeDSMCustomScan) (struct CustomScanState *node,
- struct ParallelContext *pcxt,
- void *coordinate);
- void (*InitializeWorkerCustomScan) (struct CustomScanState *node,
- struct shm_toc *toc,
- void *coordinate);
- /* Optional: print additional information in EXPLAIN */
- void (*ExplainCustomScan) (struct CustomScanState *node,
- List *ancestors,
- struct ExplainState *es);
-} CustomExecMethods;
+struct CustomExecMethods;
typedef struct CustomScanState
{
@@ -1645,7 +1614,7 @@ typedef struct CustomScanState
uint32 flags; /* mask of CUSTOMPATH_* flags, see relation.h */
List *custom_ps; /* list of child PlanState nodes, if any */
Size pscan_len; /* size of parallel coordination information */
- const CustomExecMethods *methods;
+ const struct CustomExecMethods *methods;
} CustomScanState;
/* ----------------------------------------------------------------
diff --git a/src/include/nodes/extensible.h b/src/include/nodes/extensible.h
index 96ae7bc9291..9df1377a8e6 100644
--- a/src/include/nodes/extensible.h
+++ b/src/include/nodes/extensible.h
@@ -1,7 +1,7 @@
/*-------------------------------------------------------------------------
*
* extensible.h
- * Definitions for extensible node type
+ * Definitions for extensible nodes and custom scans
*
*
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
@@ -14,8 +14,13 @@
#ifndef EXTENSIBLE_H
#define EXTENSIBLE_H
-#include "nodes/nodes.h"
+#include "access/parallel.h"
+#include "commands/explain.h"
+#include "nodes/execnodes.h"
+#include "nodes/plannodes.h"
+#include "nodes/relation.h"
+/* maximum length of an extensible node identifier */
#define EXTNODENAME_MAX_LEN 64
/*
@@ -69,4 +74,80 @@ extern void RegisterExtensibleNodeMethods(const ExtensibleNodeMethods *method);
extern const ExtensibleNodeMethods *GetExtensibleNodeMethods(const char *name,
bool missing_ok);
+/*
+ * Flags for custom paths, indicating what capabilities the resulting scan
+ * will have.
+ */
+#define CUSTOMPATH_SUPPORT_BACKWARD_SCAN 0x0001
+#define CUSTOMPATH_SUPPORT_MARK_RESTORE 0x0002
+
+/*
+ * Custom path methods. Mostly, we just need to know how to convert a
+ * CustomPath to a plan.
+ */
+typedef struct CustomPathMethods
+{
+ const char *CustomName;
+
+ /* Convert Path to a Plan */
+ struct Plan *(*PlanCustomPath) (PlannerInfo *root,
+ RelOptInfo *rel,
+ struct CustomPath *best_path,
+ List *tlist,
+ List *clauses,
+ List *custom_plans);
+} CustomPathMethods;
+
+/*
+ * Custom scan. Here again, there's not much to do: we need to be able to
+ * generate a ScanState corresponding to the scan.
+ */
+typedef struct CustomScanMethods
+{
+ const char *CustomName;
+
+ /* Create execution state (CustomScanState) from a CustomScan plan node */
+ Node *(*CreateCustomScanState) (CustomScan *cscan);
+} CustomScanMethods;
+
+/*
+ * Execution-time methods for a CustomScanState. This is more complex than
+ * what we need for a custom path or scan.
+ */
+typedef struct CustomExecMethods
+{
+ const char *CustomName;
+
+ /* Required executor methods */
+ void (*BeginCustomScan) (CustomScanState *node,
+ EState *estate,
+ int eflags);
+ TupleTableSlot *(*ExecCustomScan) (CustomScanState *node);
+ void (*EndCustomScan) (CustomScanState *node);
+ void (*ReScanCustomScan) (CustomScanState *node);
+
+ /* Optional methods: needed if mark/restore is supported */
+ void (*MarkPosCustomScan) (CustomScanState *node);
+ void (*RestrPosCustomScan) (CustomScanState *node);
+
+ /* Optional methods: needed if parallel execution is supported */
+ Size (*EstimateDSMCustomScan) (CustomScanState *node,
+ ParallelContext *pcxt);
+ void (*InitializeDSMCustomScan) (CustomScanState *node,
+ ParallelContext *pcxt,
+ void *coordinate);
+ void (*InitializeWorkerCustomScan) (CustomScanState *node,
+ shm_toc *toc,
+ void *coordinate);
+
+ /* Optional: print additional information in EXPLAIN */
+ void (*ExplainCustomScan) (CustomScanState *node,
+ List *ancestors,
+ ExplainState *es);
+} CustomExecMethods;
+
+extern void RegisterCustomScanMethods(const CustomScanMethods *methods);
+extern const CustomScanMethods *GetCustomScanMethods(const char *CustomName,
+ bool missing_ok);
+
#endif /* EXTENSIBLE_H */
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 00b1d35d759..465d72fe890 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -555,17 +555,7 @@ typedef struct ForeignScan
* a larger struct will not work.
* ----------------
*/
-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);
-} CustomScanMethods;
+struct CustomScanMethods;
typedef struct CustomScan
{
@@ -577,7 +567,7 @@ typedef struct CustomScan
List *custom_scan_tlist; /* optional tlist describing scan
* tuple */
Bitmapset *custom_relids; /* RTIs generated by this scan */
- const CustomScanMethods *methods;
+ const struct CustomScanMethods *methods;
} CustomScan;
/*
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index ee7007aacec..32f04b25dde 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -1030,23 +1030,8 @@ typedef struct ForeignPath
* FDW case, we provide a "custom_private" field in CustomPath; providers
* may prefer to use that rather than define another struct type.
*/
-struct CustomPath;
-#define CUSTOMPATH_SUPPORT_BACKWARD_SCAN 0x0001
-#define CUSTOMPATH_SUPPORT_MARK_RESTORE 0x0002
-
-typedef struct CustomPathMethods
-{
- const char *CustomName;
-
- /* Convert Path to a Plan */
- struct Plan *(*PlanCustomPath) (PlannerInfo *root,
- RelOptInfo *rel,
- struct CustomPath *best_path,
- List *tlist,
- List *clauses,
- List *custom_plans);
-} CustomPathMethods;
+struct CustomPathMethods;
typedef struct CustomPath
{
@@ -1054,7 +1039,7 @@ typedef struct CustomPath
uint32 flags; /* mask of CUSTOMPATH_* flags, see above */
List *custom_paths; /* list of child Path nodes, if any */
List *custom_private;
- const CustomPathMethods *methods;
+ const struct CustomPathMethods *methods;
} CustomPath;
/*