Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * extensible.c
4 : : * Support for extensible node types
5 : : *
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.
12 : : *
13 : : * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
14 : : * Portions Copyright (c) 1994, Regents of the University of California
15 : : *
16 : : * IDENTIFICATION
17 : : * src/backend/nodes/extensible.c
18 : : *
19 : : *-------------------------------------------------------------------------
20 : : */
21 : : #include "postgres.h"
22 : :
23 : : #include "nodes/extensible.h"
24 : : #include "utils/hsearch.h"
25 : :
26 : : static HTAB *extensible_node_methods = NULL;
27 : : static HTAB *custom_scan_methods = NULL;
28 : :
29 : : typedef struct
30 : : {
31 : : char extnodename[EXTNODENAME_MAX_LEN];
32 : : const void *extnodemethods;
33 : : } ExtensibleNodeEntry;
34 : :
35 : : /*
36 : : * An internal function to register a new callback structure
37 : : */
38 : : static void
2938 rhaas@postgresql.org 39 :UBC 0 : RegisterExtensibleNodeEntry(HTAB **p_htable, const char *htable_label,
40 : : const char *extnodename,
41 : : const void *extnodemethods)
42 : : {
43 : : ExtensibleNodeEntry *entry;
44 : : bool found;
45 : :
46 [ # # ]: 0 : if (*p_htable == NULL)
47 : : {
48 : : HASHCTL ctl;
49 : :
2966 50 : 0 : ctl.keysize = EXTNODENAME_MAX_LEN;
2984 51 : 0 : ctl.entrysize = sizeof(ExtensibleNodeEntry);
52 : :
1216 tgl@sss.pgh.pa.us 53 : 0 : *p_htable = hash_create(htable_label, 100, &ctl,
54 : : HASH_ELEM | HASH_STRINGS);
55 : : }
56 : :
2938 rhaas@postgresql.org 57 [ # # ]: 0 : if (strlen(extnodename) >= EXTNODENAME_MAX_LEN)
2953 58 [ # # ]: 0 : elog(ERROR, "extensible node name is too long");
59 : :
2938 60 : 0 : entry = (ExtensibleNodeEntry *) hash_search(*p_htable,
61 : : extnodename,
62 : : HASH_ENTER, &found);
2984 63 [ # # ]: 0 : if (found)
64 [ # # ]: 0 : ereport(ERROR,
65 : : (errcode(ERRCODE_DUPLICATE_OBJECT),
66 : : errmsg("extensible node type \"%s\" already exists",
67 : : extnodename)));
68 : :
2938 69 : 0 : entry->extnodemethods = extnodemethods;
2984 70 : 0 : }
71 : :
72 : : /*
73 : : * Register a new type of extensible node.
74 : : */
75 : : void
2938 76 : 0 : RegisterExtensibleNodeMethods(const ExtensibleNodeMethods *methods)
77 : : {
78 : 0 : RegisterExtensibleNodeEntry(&extensible_node_methods,
79 : : "Extensible Node Methods",
80 : 0 : methods->extnodename,
81 : : methods);
82 : 0 : }
83 : :
84 : : /*
85 : : * Register a new type of custom scan node
86 : : */
87 : : void
88 : 0 : RegisterCustomScanMethods(const CustomScanMethods *methods)
89 : : {
90 : 0 : RegisterExtensibleNodeEntry(&custom_scan_methods,
91 : : "Custom Scan Methods",
92 : 0 : methods->CustomName,
93 : : methods);
94 : 0 : }
95 : :
96 : : /*
97 : : * An internal routine to get an ExtensibleNodeEntry by the given identifier
98 : : */
99 : : static const void *
100 : 0 : GetExtensibleNodeEntry(HTAB *htable, const char *extnodename, bool missing_ok)
101 : : {
2984 102 : 0 : ExtensibleNodeEntry *entry = NULL;
103 : :
2938 104 [ # # ]: 0 : if (htable != NULL)
105 : 0 : entry = (ExtensibleNodeEntry *) hash_search(htable,
106 : : extnodename,
107 : : HASH_FIND, NULL);
2984 108 [ # # ]: 0 : if (!entry)
109 : : {
110 [ # # ]: 0 : if (missing_ok)
111 : 0 : return NULL;
112 [ # # ]: 0 : ereport(ERROR,
113 : : (errcode(ERRCODE_UNDEFINED_OBJECT),
114 : : errmsg("ExtensibleNodeMethods \"%s\" was not registered",
115 : : extnodename)));
116 : : }
117 : :
2938 118 : 0 : return entry->extnodemethods;
119 : : }
120 : :
121 : : /*
122 : : * Get the methods for a given type of extensible node.
123 : : */
124 : : const ExtensibleNodeMethods *
125 : 0 : GetExtensibleNodeMethods(const char *extnodename, bool missing_ok)
126 : : {
127 : 0 : return (const ExtensibleNodeMethods *)
128 : 0 : GetExtensibleNodeEntry(extensible_node_methods,
129 : : extnodename,
130 : : missing_ok);
131 : : }
132 : :
133 : : /*
134 : : * Get the methods for a given name of CustomScanMethods
135 : : */
136 : : const CustomScanMethods *
137 : 0 : GetCustomScanMethods(const char *CustomName, bool missing_ok)
138 : : {
139 : 0 : return (const CustomScanMethods *)
140 : 0 : GetExtensibleNodeEntry(custom_scan_methods,
141 : : CustomName,
142 : : missing_ok);
143 : : }
|