PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
extensible.c
Go to the documentation of this file.
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-2017, 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 
28 
29 typedef struct
30 {
31  char extnodename[EXTNODENAME_MAX_LEN];
32  const void *extnodemethods;
34 
35 /*
36  * An internal function to register a new callback structure
37  */
38 static void
39 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  if (*p_htable == NULL)
47  {
48  HASHCTL ctl;
49 
50  memset(&ctl, 0, sizeof(HASHCTL));
52  ctl.entrysize = sizeof(ExtensibleNodeEntry);
53 
54  *p_htable = hash_create(htable_label, 100, &ctl, HASH_ELEM);
55  }
56 
57  if (strlen(extnodename) >= EXTNODENAME_MAX_LEN)
58  elog(ERROR, "extensible node name is too long");
59 
60  entry = (ExtensibleNodeEntry *) hash_search(*p_htable,
61  extnodename,
62  HASH_ENTER, &found);
63  if (found)
64  ereport(ERROR,
66  errmsg("extensible node type \"%s\" already exists",
67  extnodename)));
68 
69  entry->extnodemethods = extnodemethods;
70 }
71 
72 /*
73  * Register a new type of extensible node.
74  */
75 void
77 {
78  RegisterExtensibleNodeEntry(&extensible_node_methods,
79  "Extensible Node Methods",
80  methods->extnodename,
81  methods);
82 }
83 
84 /*
85  * Register a new type of custom scan node
86  */
87 void
89 {
90  RegisterExtensibleNodeEntry(&custom_scan_methods,
91  "Custom Scan Methods",
92  methods->CustomName,
93  methods);
94 }
95 
96 /*
97  * An internal routine to get an ExtensibleNodeEntry by the given identifier
98  */
99 static const void *
100 GetExtensibleNodeEntry(HTAB *htable, const char *extnodename, bool missing_ok)
101 {
102  ExtensibleNodeEntry *entry = NULL;
103 
104  if (htable != NULL)
105  entry = (ExtensibleNodeEntry *) hash_search(htable,
106  extnodename,
107  HASH_FIND, NULL);
108  if (!entry)
109  {
110  if (missing_ok)
111  return NULL;
112  ereport(ERROR,
113  (errcode(ERRCODE_UNDEFINED_OBJECT),
114  errmsg("ExtensibleNodeMethods \"%s\" was not registered",
115  extnodename)));
116  }
117 
118  return entry->extnodemethods;
119 }
120 
121 /*
122  * Get the methods for a given type of extensible node.
123  */
124 const ExtensibleNodeMethods *
125 GetExtensibleNodeMethods(const char *extnodename, bool missing_ok)
126 {
127  return (const ExtensibleNodeMethods *)
128  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 GetCustomScanMethods(const char *CustomName, bool missing_ok)
138 {
139  return (const CustomScanMethods *)
140  GetExtensibleNodeEntry(custom_scan_methods,
141  CustomName,
142  missing_ok);
143 }
const void * extnodemethods
Definition: extensible.c:32
const char * extnodename
Definition: extensible.h:62
#define HASH_ELEM
Definition: hsearch.h:87
static void RegisterExtensibleNodeEntry(HTAB **p_htable, const char *htable_label, const char *extnodename, const void *extnodemethods)
Definition: extensible.c:39
Size entrysize
Definition: hsearch.h:73
static HTAB * extensible_node_methods
Definition: extensible.c:26
int errcode(int sqlerrcode)
Definition: elog.c:575
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:903
static const void * GetExtensibleNodeEntry(HTAB *htable, const char *extnodename, bool missing_ok)
Definition: extensible.c:100
Definition: dynahash.c:208
static HTAB * custom_scan_methods
Definition: extensible.c:27
#define ERROR
Definition: elog.h:43
const char * CustomName
Definition: extensible.h:107
#define ereport(elevel, rest)
Definition: elog.h:122
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
Size keysize
Definition: hsearch.h:72
#define NULL
Definition: c.h:229
void RegisterCustomScanMethods(const CustomScanMethods *methods)
Definition: extensible.c:88
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
void RegisterExtensibleNodeMethods(const ExtensibleNodeMethods *methods)
Definition: extensible.c:76
#define EXTNODENAME_MAX_LEN
Definition: extensible.h:24
const CustomScanMethods * GetCustomScanMethods(const char *CustomName, bool missing_ok)
Definition: extensible.c:137
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
const ExtensibleNodeMethods * GetExtensibleNodeMethods(const char *extnodename, bool missing_ok)
Definition: extensible.c:125