mirror of
https://github.com/postgres/postgres.git
synced 2025-08-22 21:53:06 +03:00
Rework custom scans to work more like the new extensible node stuff.
Per discussion, the new extensible node framework is thought to be better designed than the custom path/scan/scanstate stuff we added in PostgreSQL 9.5. Rework the latter to be more like the former. This is not backward-compatible, but we generally don't promise that for C APIs, and there probably aren't many people using this yet anyway. KaiGai Kohei, reviewed by Petr Jelinek and me. Some further cosmetic changes by me.
This commit is contained in:
@@ -24,61 +24,87 @@
|
||||
#include "utils/hsearch.h"
|
||||
|
||||
static HTAB *extensible_node_methods = NULL;
|
||||
static HTAB *custom_scan_methods = NULL;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char extnodename[EXTNODENAME_MAX_LEN];
|
||||
const ExtensibleNodeMethods *methods;
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
if (strlen(methods->extnodename) >= EXTNODENAME_MAX_LEN)
|
||||
elog(ERROR, "extensible node name is too long");
|
||||
|
||||
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;
|
||||
RegisterExtensibleNodeEntry(&extensible_node_methods,
|
||||
"Extensible Node Methods",
|
||||
methods->extnodename,
|
||||
methods);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the methods for a given type of extensible node.
|
||||
* Register a new type of custom scan node
|
||||
*/
|
||||
const ExtensibleNodeMethods *
|
||||
GetExtensibleNodeMethods(const char *extnodename, bool missing_ok)
|
||||
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 (extensible_node_methods != NULL)
|
||||
entry = (ExtensibleNodeEntry *) hash_search(extensible_node_methods,
|
||||
if (htable != NULL)
|
||||
entry = (ExtensibleNodeEntry *) hash_search(htable,
|
||||
extnodename,
|
||||
HASH_FIND, NULL);
|
||||
|
||||
if (!entry)
|
||||
{
|
||||
if (missing_ok)
|
||||
@@ -89,5 +115,29 @@ GetExtensibleNodeMethods(const char *extnodename, bool missing_ok)
|
||||
extnodename)));
|
||||
}
|
||||
|
||||
return entry->methods;
|
||||
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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user