115 lines
5.0 KiB
Plaintext
115 lines
5.0 KiB
Plaintext
src/backend/nodes/README
|
|
|
|
Node Structures
|
|
===============
|
|
|
|
Introduction
|
|
------------
|
|
|
|
Postgres uses "node" types to organize parse trees, plan trees, and
|
|
executor state trees. All objects that can appear in such trees must
|
|
be declared as node types. In addition, a few object types that aren't
|
|
part of parse/plan/execute node trees receive NodeTags anyway for
|
|
identification purposes, usually because they are involved in APIs
|
|
where we want to pass multiple object types through the same pointer.
|
|
|
|
The node structures are plain old C structures with the first field
|
|
being of type NodeTag. "Inheritance" is achieved by convention:
|
|
the first field can alternatively be of another node type.
|
|
|
|
Node types typically have support for being copied by copyObject(),
|
|
compared by equal(), serialized by outNode(), and deserialized by
|
|
nodeRead(). For some classes of Nodes, not all of these support
|
|
functions are required; for example, executor state nodes don't
|
|
presently need any of them. So far as the system is concerned,
|
|
output and read functions are only needed for node types that can
|
|
appear in parse trees stored in the catalogs, and for plan tree
|
|
nodes because those are serialized to be passed to parallel workers.
|
|
However, we provide output functions for some other node types as well,
|
|
because they are very handy for debugging. Currently, such coverage
|
|
exists for raw parsetrees and most planner data structures. However,
|
|
output coverage of raw parsetrees is incomplete: in particular, utility
|
|
statements are almost entirely unsupported.
|
|
|
|
Relevant Files
|
|
--------------
|
|
|
|
Utility functions for manipulating node structures reside in this
|
|
directory. Some support functions are automatically generated by the
|
|
gen_node_support.pl script, other functions are maintained manually.
|
|
To control the automatic generation of support functions, node types
|
|
and node fields can be annotated with pg_node_attr() specifications;
|
|
see further documentation in src/include/nodes/nodes.h.
|
|
|
|
|
|
FILES IN THIS DIRECTORY (src/backend/nodes/)
|
|
|
|
General-purpose node manipulation functions:
|
|
copyfuncs.c - copy a node tree (*)
|
|
equalfuncs.c - compare two node trees (*)
|
|
outfuncs.c - convert a node tree to text representation (*)
|
|
readfuncs.c - convert text representation back to a node tree (*)
|
|
makefuncs.c - creator functions for some common node types
|
|
nodeFuncs.c - some other general-purpose manipulation functions
|
|
queryjumblefuncs.c - compute a node tree for query jumbling (*)
|
|
|
|
(*) - Most functions in these files are generated by
|
|
gen_node_support.pl and #include'd there.
|
|
|
|
Specialized manipulation functions:
|
|
bitmapset.c - Bitmapset support
|
|
list.c - generic list support
|
|
multibitmapset.c - List-of-Bitmapset support
|
|
params.c - Param support
|
|
tidbitmap.c - TIDBitmap support
|
|
value.c - support for value nodes
|
|
|
|
FILES IN src/include/nodes/
|
|
|
|
Node definitions primarily appear in:
|
|
nodes.h - define node tags (NodeTag) (*)
|
|
primnodes.h - primitive nodes
|
|
parsenodes.h - parse tree nodes
|
|
pathnodes.h - path tree nodes and planner internal structures
|
|
plannodes.h - plan tree nodes
|
|
execnodes.h - executor nodes
|
|
memnodes.h - memory nodes
|
|
pg_list.h - generic list
|
|
|
|
(*) - Also #include's files generated by gen_node_support.pl.
|
|
|
|
|
|
Steps to Add a Node
|
|
-------------------
|
|
|
|
Suppose you want to define a node Foo:
|
|
|
|
1. Add the structure definition to the appropriate include/nodes/???.h file.
|
|
If you intend to inherit from, say a Plan node, put Plan as the first field
|
|
of your struct definition. (The T_Foo tag is created automatically.)
|
|
2. Check that the generated support functions in copyfuncs.funcs.c,
|
|
equalfuncs.funcs.c, outfuncs.funcs.c, queryjumblefuncs.funcs.c and
|
|
readfuncs.funcs.c look correct. Add attributes as necessary to control the
|
|
outcome. (For some classes of node types, you don't need all the support
|
|
functions. Use node attributes similar to those of related node types.)
|
|
3. Add cases to the functions in nodeFuncs.c as needed. There are many
|
|
other places you'll probably also need to teach about your new node
|
|
type. Best bet is to grep for references to one or two similar existing
|
|
node types to find all the places to touch.
|
|
(Except for frequently-created nodes, don't bother writing a creator
|
|
function in makefuncs.c.)
|
|
4. Consider testing your new code with COPY_PARSE_PLAN_TREES,
|
|
WRITE_READ_PARSE_PLAN_TREES, and RAW_EXPRESSION_COVERAGE_TEST to ensure
|
|
support has been added everywhere that it's necessary; see
|
|
pg_config_manual.h about these.
|
|
|
|
Adding a new node type moves the numbers associated with existing
|
|
tags, so you'll need to recompile the whole tree after doing this.
|
|
(--enable-depend usually helps.) It doesn't force initdb though,
|
|
because the numbers never go to disk. But altering or removing a node
|
|
type should usually be accompanied by an initdb-forcing catalog
|
|
version change, since the interpretation of serialized node trees
|
|
stored in system catalogs is affected by that. (If the node type
|
|
never appears in stored parse trees, as for example Plan nodes do not,
|
|
then a catversion change is not needed to change it.)
|