executor-and-plannerlisted
Install: claude install-skill matejformanek/postgres-claude
# Executor & Planner — operational
Companion docs: `knowledge/architecture/executor.md`, `knowledge/architecture/planner.md`,
`knowledge/architecture/query-lifecycle.md`.
The executor and planner are coupled by the Path-then-Plan handoff and by the
1:1 correspondence between plan-node types and executor node types. If you add
a new way to execute something, you almost always touch both subsystems.
---
## Part A — Adding a new executor node
A node type has **four** trees to keep in sync: `Plan` (plannodes.h),
`PlanState` (execnodes.h), the Path that builds it (pathnodes.h, optional if
your node is only emitted by a special-case planner path), and the dispatch
switches in `execProcnode.c`. Skipping any one of these compiles cleanly and
fails at run time with `unrecognized node type`.
### A.1 The five-or-six functions to implement
For a new node `Foo`, in `src/backend/executor/nodeFoo.c` plus header
`src/include/executor/nodeFoo.h` (see `parser-and-nodes` skill for the
NodeTag / copy / equal / out / read machinery you'll need before any of
this compiles — also recapped in A.6):
| Function | Purpose | Pattern |
|----------|---------|---------|
| `ExecInitFoo(Foo *node, EState *estate, int eflags)` | Build `FooState`, recursively init children, allocate ExprContext, init quals/projection, set `ExecProcNode`. | See `ExecInitSeqScan` (`nodeSeqscan.c:220`). |
| `ExecFoo(PlanState *pstate)` | The pull-iterator. Return next `TupleTableSlot *`, or empty slot when exhausted. Stat