/*------------------------------------------------------------------------- * * extensible.h * Definitions for extensible nodes and custom scans * * * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/extensible.h * *------------------------------------------------------------------------- */ #ifndef EXTENSIBLE_H #define EXTENSIBLE_H #include "access/parallel.h" #include "commands/explain.h" #include "nodes/execnodes.h" #include "nodes/pathnodes.h" #include "nodes/plannodes.h" /* maximum length of an extensible node identifier */ #define EXTNODENAME_MAX_LEN 64 /* * An extensible node is a new type of node defined by an extension. The * type is always T_ExtensibleNode, while the extnodename identifies the * specific type of node. extnodename can be looked up to find the * ExtensibleNodeMethods for this node type. */ typedef struct ExtensibleNode { pg_node_attr(custom_copy_equal, custom_read_write) NodeTag type; const char *extnodename; /* identifier of ExtensibleNodeMethods */ } ExtensibleNode; /* * node_size is the size of an extensible node of this type in bytes. * * nodeCopy is a function which performs a deep copy from oldnode to newnode. * It does not need to copy type or extnodename, which are copied by the * core system. * * nodeEqual is a function which performs a deep equality comparison between * a and b and returns true or false accordingly. It does not need to compare * type or extnodename, which are compared by the core system. * * nodeOut is a serialization function for the node type. It should use the * output conventions typical for outfuncs.c. It does not need to output * type or extnodename; the core system handles those. * * nodeRead is a deserialization function for the node type. It does not need * to read type or extnodename; the core system handles those. It should fetch * the next token using pg_strtok() from the current input stream, and then * reconstruct the private fields according to the manner in readfuncs.c. * * All callbacks are mandatory. */ typedef struct ExtensibleNodeMethods { const char *extnodename; Size node_size; void (*nodeCopy) (struct ExtensibleNode *newnode, const struct ExtensibleNode *oldnode); bool (*nodeEqual) (const struct ExtensibleNode *a, const struct ExtensibleNode *b); void (*nodeOut) (struct StringInfoData *str, const struct ExtensibleNode *node); void (*nodeRead) (struct ExtensibleNode *node); } ExtensibleNodeMethods; extern void RegisterExtensibleNodeMethods(const ExtensibleNodeMethods *methods); extern const ExtensibleNodeMethods *GetExtensibleNodeMethods(const char *extnodename, bool missing_ok); /* * Flags for custom paths, indicating what capabilities the resulting scan * will have. The flags fields of CustomPath and CustomScan nodes are * bitmasks of these flags. */ #define CUSTOMPATH_SUPPORT_BACKWARD_SCAN 0x0001 #define CUSTOMPATH_SUPPORT_MARK_RESTORE 0x0002 #define CUSTOMPATH_SUPPORT_PROJECTION 0x0004 /* * Custom path methods. Mostly, we just need to know how to convert a * CustomPath to a plan. */ typedef struct CustomPathMethods { const char *CustomName; /* Convert Path to a Plan */ struct Plan *(*PlanCustomPath) (PlannerInfo *root, RelOptInfo *rel, struct CustomPath *best_path, List *tlist, List *clauses, List *custom_plans); struct List *(*ReparameterizeCustomPathByChild) (PlannerInfo *root, List *custom_private, RelOptInfo *child_rel); } CustomPathMethods; /* * Custom scan. Here again, there's not much to do: we need to be able to * generate a ScanState corresponding to the scan. */ typedef struct CustomScanMethods { const char *CustomName; /* Create execution state (CustomScanState) from a CustomScan plan node */ Node *(*CreateCustomScanState) (CustomScan *cscan); } CustomScanMethods; /* * Execution-time methods for a CustomScanState. This is more complex than * what we need for a custom path or scan. */ typedef struct CustomExecMethods { const char *CustomName; /* Required executor methods */ void (*BeginCustomScan) (CustomScanState *node, EState *estate, int eflags); TupleTableSlot *(*ExecCustomScan) (CustomScanState *node); void (*EndCustomScan) (CustomScanState *node); void (*ReScanCustomScan) (CustomScanState *node); /* Optional methods: needed if mark/restore is supported */ void (*MarkPosCustomScan) (CustomScanState *node); void (*RestrPosCustomScan) (CustomScanState *node); /* Optional methods: needed if parallel execution is supported */ Size (*EstimateDSMCustomScan) (CustomScanState *node, ParallelContext *pcxt); void (*InitializeDSMCustomScan) (CustomScanState *node, ParallelContext *pcxt, void *coordinate); void (*ReInitializeDSMCustomScan) (CustomScanState *node, ParallelContext *pcxt, void *coordinate); void (*InitializeWorkerCustomScan) (CustomScanState *node, shm_toc *toc, void *coordinate); void (*ShutdownCustomScan) (CustomScanState *node); /* Optional: print additional information in EXPLAIN */ void (*ExplainCustomScan) (CustomScanState *node, List *ancestors, ExplainState *es); } CustomExecMethods; extern void RegisterCustomScanMethods(const CustomScanMethods *methods); extern const CustomScanMethods *GetCustomScanMethods(const char *CustomName, bool missing_ok); #endif /* EXTENSIBLE_H */