{"kind": "hook", "major": "18", "item": {"slug": "explain_per_node_hook", "name": "explain_per_node_hook", "name_zh": "explain_per_node_hook", "category": "EXPLAIN", "summary": "Hook for EXPLAIN plugins to print extra fields on individual plan nodes", "aliases": [], "versions": {"18": {"facts": [{"label": "Interface type", "value": "explain_per_node_hook_type"}, {"label": "Header", "value": "src/include/commands/explain.h"}, {"label": "Subsystem", "value": "EXPLAIN"}, {"label": "Initial value", "value": "NULL (no hook installed)"}], "related": [{"url": "/docs/sql/explain/?v=18", "label": "EXPLAIN"}], "release": {"ref": "REL_18_STABLE", "label": "18", "major": "18", "channel": "stable", "revision": "753057e340da8f22e57c9a409ea7a235fd6a46bd"}, "sources": [{"url": "https://github.com/postgres/postgres/blob/753057e340da8f22e57c9a409ea7a235fd6a46bd/src/include/commands/explain.h#L41", "path": "src/include/commands/explain.h", "label": "Interface declaration", "sha256": "a8ef9548bccebb3c8f5255e8295d1d53dd0e4ea54b6be8b17dfe163ef2918b7f"}, {"url": "https://github.com/postgres/postgres/blob/753057e340da8f22e57c9a409ea7a235fd6a46bd/src/backend/commands/explain.c#L57", "path": "src/backend/commands/explain.c", "label": "Core definition", "sha256": "34c86d6070224a0e981efef51f79101d6d505e5874f1684ace183034bab14bb4"}, {"url": "https://github.com/postgres/postgres/blob/753057e340da8f22e57c9a409ea7a235fd6a46bd/src/backend/commands/explain.c#L2319", "path": "src/backend/commands/explain.c", "label": "Call sites", "sha256": "34c86d6070224a0e981efef51f79101d6d505e5874f1684ace183034bab14bb4"}], "sections": [{"title": "Core source comments", "paragraphs": ["Allow plugins to print additional information"]}, {"title": "Call sites", "paragraphs": ["src/backend/commands/explain.c:2319"]}, {"code": "\tif (es->workers_state)\n\t\tExplainFlushWorkersState(es);\n\tes->workers_state = save_workers_state;\n\n\t/* Allow plugins to print additional information */\n\tif (explain_per_node_hook)\n\t\t(*explain_per_node_hook) (planstate, ancestors, relationship,\n\t\t\t\t\t\t\t\t  plan_name, es);\n\n\t/*\n\t * If partition pruning was done during executor initialization, the\n\t * number of child plans we'll display below will be less than the number\n\t * of subplans that was specified in the plan.  To make this a bit less\n\t * mysterious, emit an indication that this happened.  Note that this\n\t * field is emitted now because we want it to be a property of the parent", "title": "Core call context: src/backend/commands/explain.c:2313\u20132327", "paragraphs": []}], "signature": "typedef void (*explain_per_node_hook_type) (PlanState *planstate, List *ancestors, const char *relationship, const char *plan_name, struct ExplainState *es);\nextern PGDLLIMPORT explain_per_node_hook_type explain_per_node_hook;", "description": ["Hook for EXPLAIN plugins to print extra fields on individual plan nodes"]}, "19": {"facts": [{"label": "Interface type", "value": "explain_per_node_hook_type"}, {"label": "Header", "value": "src/include/commands/explain.h"}, {"label": "Subsystem", "value": "EXPLAIN"}, {"label": "Initial value", "value": "NULL (no hook installed)"}], "related": [{"url": "/docs/sql/explain/?v=19", "label": "EXPLAIN"}], "release": {"ref": "REL_19_BETA4", "label": "19 Beta 4", "major": "19", "channel": "preview", "revision": "b73d13c32c834a2c8e1c60cb92f79530376cedf1"}, "sources": [{"url": "https://github.com/postgres/postgres/blob/b73d13c32c834a2c8e1c60cb92f79530376cedf1/src/include/commands/explain.h#L42", "path": "src/include/commands/explain.h", "label": "Interface declaration", "sha256": "469d0dad433271caace897340b6bd44dd89b27c255687cfbf89e5050926f9c82"}, {"url": "https://github.com/postgres/postgres/blob/b73d13c32c834a2c8e1c60cb92f79530376cedf1/src/backend/commands/explain.c#L59", "path": "src/backend/commands/explain.c", "label": "Core definition", "sha256": "8b115b1c194a4b54ae630209a741e293b1df49a9052f10b2de9ca092a48998e3"}, {"url": "https://github.com/postgres/postgres/blob/b73d13c32c834a2c8e1c60cb92f79530376cedf1/src/backend/commands/explain.c#L2336", "path": "src/backend/commands/explain.c", "label": "Call sites", "sha256": "8b115b1c194a4b54ae630209a741e293b1df49a9052f10b2de9ca092a48998e3"}], "sections": [{"title": "Core source comments", "paragraphs": ["Allow plugins to print additional information"]}, {"title": "Call sites", "paragraphs": ["src/backend/commands/explain.c:2336"]}, {"code": "\tif (es->workers_state)\n\t\tExplainFlushWorkersState(es);\n\tes->workers_state = save_workers_state;\n\n\t/* Allow plugins to print additional information */\n\tif (explain_per_node_hook)\n\t\t(*explain_per_node_hook) (planstate, ancestors, relationship,\n\t\t\t\t\t\t\t\t  plan_name, es);\n\n\t/*\n\t * If partition pruning was done during executor initialization, the\n\t * number of child plans we'll display below will be less than the number\n\t * of subplans that was specified in the plan.  To make this a bit less\n\t * mysterious, emit an indication that this happened.  Note that this\n\t * field is emitted now because we want it to be a property of the parent", "title": "Core call context: src/backend/commands/explain.c:2330\u20132344", "paragraphs": []}], "signature": "typedef void (*explain_per_node_hook_type) (PlanState *planstate, List *ancestors, const char *relationship, const char *plan_name, ExplainState *es);\nextern PGDLLIMPORT explain_per_node_hook_type explain_per_node_hook;", "description": ["Hook for EXPLAIN plugins to print extra fields on individual plan nodes"]}, "20": {"facts": [{"label": "Interface type", "value": "explain_per_node_hook_type"}, {"label": "Header", "value": "src/include/commands/explain.h"}, {"label": "Subsystem", "value": "EXPLAIN"}, {"label": "Initial value", "value": "NULL (no hook installed)"}], "related": [{"url": "/docs/sql/explain/?v=20", "label": "EXPLAIN"}], "release": {"ref": "master", "label": "20 devel", "major": "20", "channel": "devel", "revision": "2c10c2ce4d7bcd57543a49ab402af02a39724e0a"}, "sources": [{"url": "https://github.com/postgres/postgres/blob/2c10c2ce4d7bcd57543a49ab402af02a39724e0a/src/include/commands/explain.h#L42", "path": "src/include/commands/explain.h", "label": "Interface declaration", "sha256": "469d0dad433271caace897340b6bd44dd89b27c255687cfbf89e5050926f9c82"}, {"url": "https://github.com/postgres/postgres/blob/2c10c2ce4d7bcd57543a49ab402af02a39724e0a/src/backend/commands/explain.c#L59", "path": "src/backend/commands/explain.c", "label": "Core definition", "sha256": "13402758013520451539427b5993db06d463ca11c4e2d4cc5444e82367688077"}, {"url": "https://github.com/postgres/postgres/blob/2c10c2ce4d7bcd57543a49ab402af02a39724e0a/src/backend/commands/explain.c#L2333", "path": "src/backend/commands/explain.c", "label": "Call sites", "sha256": "13402758013520451539427b5993db06d463ca11c4e2d4cc5444e82367688077"}], "sections": [{"title": "Core source comments", "paragraphs": ["Allow plugins to print additional information"]}, {"title": "Call sites", "paragraphs": ["src/backend/commands/explain.c:2333"]}, {"code": "\tif (es->workers_state)\n\t\tExplainFlushWorkersState(es);\n\tes->workers_state = save_workers_state;\n\n\t/* Allow plugins to print additional information */\n\tif (explain_per_node_hook)\n\t\t(*explain_per_node_hook) (planstate, ancestors, relationship,\n\t\t\t\t\t\t\t\t  plan_name, es);\n\n\t/*\n\t * If partition pruning was done during executor initialization, the\n\t * number of child plans we'll display below will be less than the number\n\t * of subplans that was specified in the plan.  To make this a bit less\n\t * mysterious, emit an indication that this happened.  Note that this\n\t * field is emitted now because we want it to be a property of the parent", "title": "Core call context: src/backend/commands/explain.c:2327\u20132341", "paragraphs": []}], "signature": "typedef void (*explain_per_node_hook_type) (PlanState *planstate, List *ancestors, const char *relationship, const char *plan_name, ExplainState *es);\nextern PGDLLIMPORT explain_per_node_hook_type explain_per_node_hook;", "description": ["Hook for EXPLAIN plugins to print extra fields on individual plan nodes"]}}, "content_hash": "0d43c00ca717eea9832f82c014e0cbc32e48fd75c4649482b06d6c4affd32bd6", "imported_at": "2026-09-27T09:57:58.834"}, "snapshot": {"facts": [{"label": "Interface type", "value": "explain_per_node_hook_type"}, {"label": "Header", "value": "src/include/commands/explain.h"}, {"label": "Subsystem", "value": "EXPLAIN"}, {"label": "Initial value", "value": "NULL (no hook installed)"}], "related": [{"url": "/docs/sql/explain/?v=18", "label": "EXPLAIN"}], "release": {"ref": "REL_18_STABLE", "label": "18", "major": "18", "channel": "stable", "revision": "753057e340da8f22e57c9a409ea7a235fd6a46bd"}, "sources": [{"url": "https://github.com/postgres/postgres/blob/753057e340da8f22e57c9a409ea7a235fd6a46bd/src/include/commands/explain.h#L41", "path": "src/include/commands/explain.h", "label": "Interface declaration", "sha256": "a8ef9548bccebb3c8f5255e8295d1d53dd0e4ea54b6be8b17dfe163ef2918b7f"}, {"url": "https://github.com/postgres/postgres/blob/753057e340da8f22e57c9a409ea7a235fd6a46bd/src/backend/commands/explain.c#L57", "path": "src/backend/commands/explain.c", "label": "Core definition", "sha256": "34c86d6070224a0e981efef51f79101d6d505e5874f1684ace183034bab14bb4"}, {"url": "https://github.com/postgres/postgres/blob/753057e340da8f22e57c9a409ea7a235fd6a46bd/src/backend/commands/explain.c#L2319", "path": "src/backend/commands/explain.c", "label": "Call sites", "sha256": "34c86d6070224a0e981efef51f79101d6d505e5874f1684ace183034bab14bb4"}], "sections": [{"title": "Core source comments", "paragraphs": ["Allow plugins to print additional information"]}, {"title": "Call sites", "paragraphs": ["src/backend/commands/explain.c:2319"]}, {"code": "\tif (es->workers_state)\n\t\tExplainFlushWorkersState(es);\n\tes->workers_state = save_workers_state;\n\n\t/* Allow plugins to print additional information */\n\tif (explain_per_node_hook)\n\t\t(*explain_per_node_hook) (planstate, ancestors, relationship,\n\t\t\t\t\t\t\t\t  plan_name, es);\n\n\t/*\n\t * If partition pruning was done during executor initialization, the\n\t * number of child plans we'll display below will be less than the number\n\t * of subplans that was specified in the plan.  To make this a bit less\n\t * mysterious, emit an indication that this happened.  Note that this\n\t * field is emitted now because we want it to be a property of the parent", "title": "Core call context: src/backend/commands/explain.c:2313\u20132327", "paragraphs": []}], "signature": "typedef void (*explain_per_node_hook_type) (PlanState *planstate, List *ancestors, const char *relationship, const char *plan_name, struct ExplainState *es);\nextern PGDLLIMPORT explain_per_node_hook_type explain_per_node_hook;", "description": ["Hook for EXPLAIN plugins to print extra fields on individual plan nodes"]}, "comparison": {"left": "17", "right": "18", "status": "added", "diff": "--- PostgreSQL 17\n+++ PostgreSQL 18\n@@ -1 +1,22 @@\n-Not recorded in this version\n+{\n+  \"facts\": [\n+    {\n+      \"label\": \"Interface type\",\n+      \"value\": \"explain_per_node_hook_type\"\n+    },\n+    {\n+      \"label\": \"Header\",\n+      \"value\": \"src/include/commands/explain.h\"\n+    },\n+    {\n+      \"label\": \"Subsystem\",\n+      \"value\": \"EXPLAIN\"\n+    },\n+    {\n+      \"label\": \"Initial value\",\n+      \"value\": \"NULL (no hook installed)\"\n+    }\n+  ],\n+  \"signature\": \"typedef void (*explain_per_node_hook_type) (PlanState *planstate, List *ancestors, const char *relationship, const char *plan_name, struct ExplainState *es);\\nextern PGDLLIMPORT explain_per_node_hook_type explain_per_node_hook;\",\n+  \"tables\": null\n+}"}}