summaryrefslogtreecommitdiffstats
path: root/src/backend/nodes/extensible.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:17:33 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:17:33 +0000
commit5e45211a64149b3c659b90ff2de6fa982a5a93ed (patch)
tree739caf8c461053357daa9f162bef34516c7bf452 /src/backend/nodes/extensible.c
parentInitial commit. (diff)
downloadpostgresql-15-5e45211a64149b3c659b90ff2de6fa982a5a93ed.tar.xz
postgresql-15-5e45211a64149b3c659b90ff2de6fa982a5a93ed.zip
Adding upstream version 15.5.upstream/15.5
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/backend/nodes/extensible.c')
-rw-r--r--src/backend/nodes/extensible.c143
1 files changed, 143 insertions, 0 deletions
diff --git a/src/backend/nodes/extensible.c b/src/backend/nodes/extensible.c
new file mode 100644
index 0000000..50db4c1
--- /dev/null
+++ b/src/backend/nodes/extensible.c
@@ -0,0 +1,143 @@
+/*-------------------------------------------------------------------------
+ *
+ * extensible.c
+ * Support for extensible node types
+ *
+ * Loadable modules can define what are in effect new types of nodes using
+ * the routines in this file. All such nodes are flagged T_ExtensibleNode,
+ * with the extnodename field distinguishing the specific type. Use
+ * RegisterExtensibleNodeMethods to register a new type of extensible node,
+ * and GetExtensibleNodeMethods to get information about a previously
+ * registered type of extensible node.
+ *
+ * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/backend/nodes/extensible.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "nodes/extensible.h"
+#include "utils/hsearch.h"
+
+static HTAB *extensible_node_methods = NULL;
+static HTAB *custom_scan_methods = NULL;
+
+typedef struct
+{
+ char extnodename[EXTNODENAME_MAX_LEN];
+ const void *extnodemethods;
+} ExtensibleNodeEntry;
+
+/*
+ * An internal function to register a new callback structure
+ */
+static void
+RegisterExtensibleNodeEntry(HTAB **p_htable, const char *htable_label,
+ const char *extnodename,
+ const void *extnodemethods)
+{
+ ExtensibleNodeEntry *entry;
+ bool found;
+
+ if (*p_htable == NULL)
+ {
+ HASHCTL ctl;
+
+ ctl.keysize = EXTNODENAME_MAX_LEN;
+ ctl.entrysize = sizeof(ExtensibleNodeEntry);
+
+ *p_htable = hash_create(htable_label, 100, &ctl,
+ HASH_ELEM | HASH_STRINGS);
+ }
+
+ if (strlen(extnodename) >= EXTNODENAME_MAX_LEN)
+ elog(ERROR, "extensible node name is too long");
+
+ 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",
+ extnodename)));
+
+ entry->extnodemethods = extnodemethods;
+}
+
+/*
+ * Register a new type of extensible node.
+ */
+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 (htable != NULL)
+ entry = (ExtensibleNodeEntry *) hash_search(htable,
+ extnodename,
+ HASH_FIND, NULL);
+ if (!entry)
+ {
+ if (missing_ok)
+ return NULL;
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("ExtensibleNodeMethods \"%s\" was not registered",
+ extnodename)));
+ }
+
+ 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);
+}