Update copyright for 2022
[pgsql.git] / src / backend / nodes / extensible.c
blob50db4c119ed010879873e6d2010a7d93c53ff8f1
1 /*-------------------------------------------------------------------------
3 * extensible.c
4 * Support for extensible node types
6 * Loadable modules can define what are in effect new types of nodes using
7 * the routines in this file. All such nodes are flagged T_ExtensibleNode,
8 * with the extnodename field distinguishing the specific type. Use
9 * RegisterExtensibleNodeMethods to register a new type of extensible node,
10 * and GetExtensibleNodeMethods to get information about a previously
11 * registered type of extensible node.
13 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
14 * Portions Copyright (c) 1994, Regents of the University of California
16 * IDENTIFICATION
17 * src/backend/nodes/extensible.c
19 *-------------------------------------------------------------------------
21 #include "postgres.h"
23 #include "nodes/extensible.h"
24 #include "utils/hsearch.h"
26 static HTAB *extensible_node_methods = NULL;
27 static HTAB *custom_scan_methods = NULL;
29 typedef struct
31 char extnodename[EXTNODENAME_MAX_LEN];
32 const void *extnodemethods;
33 } ExtensibleNodeEntry;
36 * An internal function to register a new callback structure
38 static void
39 RegisterExtensibleNodeEntry(HTAB **p_htable, const char *htable_label,
40 const char *extnodename,
41 const void *extnodemethods)
43 ExtensibleNodeEntry *entry;
44 bool found;
46 if (*p_htable == NULL)
48 HASHCTL ctl;
50 ctl.keysize = EXTNODENAME_MAX_LEN;
51 ctl.entrysize = sizeof(ExtensibleNodeEntry);
53 *p_htable = hash_create(htable_label, 100, &ctl,
54 HASH_ELEM | HASH_STRINGS);
57 if (strlen(extnodename) >= EXTNODENAME_MAX_LEN)
58 elog(ERROR, "extensible node name is too long");
60 entry = (ExtensibleNodeEntry *) hash_search(*p_htable,
61 extnodename,
62 HASH_ENTER, &found);
63 if (found)
64 ereport(ERROR,
65 (errcode(ERRCODE_DUPLICATE_OBJECT),
66 errmsg("extensible node type \"%s\" already exists",
67 extnodename)));
69 entry->extnodemethods = extnodemethods;
73 * Register a new type of extensible node.
75 void
76 RegisterExtensibleNodeMethods(const ExtensibleNodeMethods *methods)
78 RegisterExtensibleNodeEntry(&extensible_node_methods,
79 "Extensible Node Methods",
80 methods->extnodename,
81 methods);
85 * Register a new type of custom scan node
87 void
88 RegisterCustomScanMethods(const CustomScanMethods *methods)
90 RegisterExtensibleNodeEntry(&custom_scan_methods,
91 "Custom Scan Methods",
92 methods->CustomName,
93 methods);
97 * An internal routine to get an ExtensibleNodeEntry by the given identifier
99 static const void *
100 GetExtensibleNodeEntry(HTAB *htable, const char *extnodename, bool missing_ok)
102 ExtensibleNodeEntry *entry = NULL;
104 if (htable != NULL)
105 entry = (ExtensibleNodeEntry *) hash_search(htable,
106 extnodename,
107 HASH_FIND, NULL);
108 if (!entry)
110 if (missing_ok)
111 return NULL;
112 ereport(ERROR,
113 (errcode(ERRCODE_UNDEFINED_OBJECT),
114 errmsg("ExtensibleNodeMethods \"%s\" was not registered",
115 extnodename)));
118 return entry->extnodemethods;
122 * Get the methods for a given type of extensible node.
124 const ExtensibleNodeMethods *
125 GetExtensibleNodeMethods(const char *extnodename, bool missing_ok)
127 return (const ExtensibleNodeMethods *)
128 GetExtensibleNodeEntry(extensible_node_methods,
129 extnodename,
130 missing_ok);
134 * Get the methods for a given name of CustomScanMethods
136 const CustomScanMethods *
137 GetCustomScanMethods(const char *CustomName, bool missing_ok)
139 return (const CustomScanMethods *)
140 GetExtensibleNodeEntry(custom_scan_methods,
141 CustomName,
142 missing_ok);