postgresql/src/backend/nodes/extensible.c

93 lines
2.5 KiB
C
Raw Normal View History

/*-------------------------------------------------------------------------
*
* 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-2016, 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;
typedef struct
{
char extnodename[EXTNODENAME_MAX_LEN];
const ExtensibleNodeMethods *methods;
} ExtensibleNodeEntry;
/*
* Register a new type of extensible node.
*/
void
RegisterExtensibleNodeMethods(const ExtensibleNodeMethods *methods)
{
ExtensibleNodeEntry *entry;
bool found;
if (extensible_node_methods == 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);
}
Assert(strlen(methods->extnodename) <= EXTNODENAME_MAX_LEN);
entry = (ExtensibleNodeEntry *) hash_search(extensible_node_methods,
methods->extnodename,
HASH_ENTER, &found);
if (found)
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("extensible node type \"%s\" already exists",
methods->extnodename)));
entry->methods = methods;
}
/*
* Get the methods for a given type of extensible node.
*/
const ExtensibleNodeMethods *
GetExtensibleNodeMethods(const char *extnodename, bool missing_ok)
{
ExtensibleNodeEntry *entry = NULL;
if (extensible_node_methods != NULL)
entry = (ExtensibleNodeEntry *) hash_search(extensible_node_methods,
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->methods;
}