mirror of
https://github.com/postgres/postgres.git
synced 2025-05-17 06:41:24 +03:00
144 lines
3.6 KiB
C
144 lines
3.6 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* 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-2019, 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;
|
|
|
|
memset(&ctl, 0, sizeof(HASHCTL));
|
|
ctl.keysize = EXTNODENAME_MAX_LEN;
|
|
ctl.entrysize = sizeof(ExtensibleNodeEntry);
|
|
|
|
*p_htable = hash_create(htable_label, 100, &ctl, HASH_ELEM);
|
|
}
|
|
|
|
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);
|
|
}
|