summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Haas2016-03-29 15:00:18 +0000
committerRobert Haas2016-03-29 15:28:04 +0000
commitf9143d102ffd0947ca904c62b1d3d6fd587e0c80 (patch)
treee75fb310cbad87d2641291fec320302531f5c548
parent534da37927f97ae7cb1b468963ba9bca747209ea (diff)
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.
-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 787b0b93cc..09c230468b 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 2473b658b1..d61be58c45 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 32d03f7f25..83abaa68a3 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 6db0492e15..cb0752a6ad 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 d159a17fd2..e4bc14a151 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 410a3ad14d..9d0b393528 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 0113e5c663..bf2a09bc39 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 96ae7bc929..9df1377a8e 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 00b1d35d75..465d72fe89 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 ee7007aace..32f04b25dd 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;
/*