{"kind": "hook", "major": "18", "item": {"slug": "join_path_setup_hook", "name": "join_path_setup_hook", "name_zh": "join_path_setup_hook", "category": "Query planning", "summary": "Not recorded in the selected version.", "aliases": [], "versions": {"19": {"facts": [{"label": "Interface type", "value": "join_path_setup_hook_type"}, {"label": "Header", "value": "src/include/optimizer/paths.h"}, {"label": "Subsystem", "value": "Query planning"}, {"label": "Initial value", "value": "NULL (no hook installed)"}], "related": [{"url": "/docs/19/planner-optimizer.html", "label": "The Planner/Optimizer"}], "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/optimizer/paths.h#L32", "path": "src/include/optimizer/paths.h", "label": "Interface declaration", "sha256": "f1ad3b9072e9a7307836c33477dbb472f36bb3a2c135fa50cd1622d3750310cb"}, {"url": "https://github.com/postgres/postgres/blob/b73d13c32c834a2c8e1c60cb92f79530376cedf1/src/backend/optimizer/path/joinpath.c#L32", "path": "src/backend/optimizer/path/joinpath.c", "label": "Core definition", "sha256": "45ca2faac289f61d393e1e60cfe84725da1c233287b9fe550bd00c4452a32078"}, {"url": "https://github.com/postgres/postgres/blob/b73d13c32c834a2c8e1c60cb92f79530376cedf1/src/backend/optimizer/path/joinpath.c#L178", "path": "src/backend/optimizer/path/joinpath.c", "label": "Call sites", "sha256": "45ca2faac289f61d393e1e60cfe84725da1c233287b9fe550bd00c4452a32078"}], "sections": [{"title": "Core source comments", "paragraphs": ["Give extensions a chance to take control. In particular, an extension might want to modify extra.pgs_mask. It's possible to override pgs_mask on a query-wide basis using join_search_hook, or for a particular relation using joinrel_setup_hook, but extensions that want to provide different advice for the same joinrel based on the choice of innerrel and outerrel will need to use this hook. A very simple way for an extension to use this hook is to set extra.pgs_mask &= ~PGS_JOIN_ANY, if it simply doesn't want any of the paths generated by this call to add_paths_to_joinrel() to be selected. An extension could use this technique to constrain the join order, since it could thereby arrange to reject all paths from join orders that it does not like. An extension can also selectively clear bits from extra.pgs_mask to rule out specific techniques for specific joins, or could even set additional bits to re-allow methods disabled at some higher level. NB: Below this point, this function should be careful to reference extra.pgs_mask rather than rel->pgs_mask to avoid disregarding any changes made by the hook we're about to call."]}, {"title": "Call sites", "paragraphs": ["src/backend/optimizer/path/joinpath.c:178"]}, {"code": "\t *\n\t * NB: Below this point, this function should be careful to reference\n\t * extra.pgs_mask rather than rel->pgs_mask to avoid disregarding any\n\t * changes made by the hook we're about to call.\n\t */\n\tif (join_path_setup_hook)\n\t\tjoin_path_setup_hook(root, joinrel, outerrel, innerrel,\n\t\t\t\t\t\t\t jointype, &extra);\n\n\t/*\n\t * See if the inner relation is provably unique for this outer rel.\n\t *\n\t * We have some special cases: for JOIN_SEMI, it doesn't matter since the\n\t * executor can make the equivalent optimization anyway.  It also doesn't\n\t * help enable use of Memoize, since a semijoin with a provably unique", "title": "Core call context: src/backend/optimizer/path/joinpath.c:172\u2013186", "paragraphs": []}], "signature": "typedef void (*join_path_setup_hook_type) (PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra);\nextern PGDLLIMPORT join_path_setup_hook_type join_path_setup_hook;", "description": ["Hooks for plugins to get control in set_rel_pathlist()"]}, "20": {"facts": [{"label": "Interface type", "value": "join_path_setup_hook_type"}, {"label": "Header", "value": "src/include/optimizer/paths.h"}, {"label": "Subsystem", "value": "Query planning"}, {"label": "Initial value", "value": "NULL (no hook installed)"}], "related": [{"url": "/docs/devel/planner-optimizer.html", "label": "The Planner/Optimizer"}], "release": {"ref": "master", "label": "20 devel", "major": "20", "channel": "devel", "revision": "2c10c2ce4d7bcd57543a49ab402af02a39724e0a"}, "sources": [{"url": "https://github.com/postgres/postgres/blob/2c10c2ce4d7bcd57543a49ab402af02a39724e0a/src/include/optimizer/paths.h#L32", "path": "src/include/optimizer/paths.h", "label": "Interface declaration", "sha256": "7d4e6d888e06597a145f6e53f235a90dc70f13db5bab820339f63023003b79e3"}, {"url": "https://github.com/postgres/postgres/blob/2c10c2ce4d7bcd57543a49ab402af02a39724e0a/src/backend/optimizer/path/joinpath.c#L32", "path": "src/backend/optimizer/path/joinpath.c", "label": "Core definition", "sha256": "acf82e1a85a0ee004b15ab07db9f72a7729dcea096ffd82e509c0dc2b98b9faf"}, {"url": "https://github.com/postgres/postgres/blob/2c10c2ce4d7bcd57543a49ab402af02a39724e0a/src/backend/optimizer/path/joinpath.c#L178", "path": "src/backend/optimizer/path/joinpath.c", "label": "Call sites", "sha256": "acf82e1a85a0ee004b15ab07db9f72a7729dcea096ffd82e509c0dc2b98b9faf"}], "sections": [{"title": "Core source comments", "paragraphs": ["Give extensions a chance to take control. In particular, an extension might want to modify extra.pgs_mask. It's possible to override pgs_mask on a query-wide basis using join_search_hook, or for a particular relation using joinrel_setup_hook, but extensions that want to provide different advice for the same joinrel based on the choice of innerrel and outerrel will need to use this hook. A very simple way for an extension to use this hook is to set extra.pgs_mask &= ~PGS_JOIN_ANY, if it simply doesn't want any of the paths generated by this call to add_paths_to_joinrel() to be selected. An extension could use this technique to constrain the join order, since it could thereby arrange to reject all paths from join orders that it does not like. An extension can also selectively clear bits from extra.pgs_mask to rule out specific techniques for specific joins, or could even set additional bits to re-allow methods disabled at some higher level. NB: Below this point, this function should be careful to reference extra.pgs_mask rather than rel->pgs_mask to avoid disregarding any changes made by the hook we're about to call."]}, {"title": "Call sites", "paragraphs": ["src/backend/optimizer/path/joinpath.c:178"]}, {"code": "\t *\n\t * NB: Below this point, this function should be careful to reference\n\t * extra.pgs_mask rather than rel->pgs_mask to avoid disregarding any\n\t * changes made by the hook we're about to call.\n\t */\n\tif (join_path_setup_hook)\n\t\tjoin_path_setup_hook(root, joinrel, outerrel, innerrel,\n\t\t\t\t\t\t\t jointype, &extra);\n\n\t/*\n\t * See if the inner relation is provably unique for this outer rel.\n\t *\n\t * We have some special cases: for JOIN_SEMI, it doesn't matter since the\n\t * executor can make the equivalent optimization anyway.  It also doesn't\n\t * help enable use of Memoize, since a semijoin with a provably unique", "title": "Core call context: src/backend/optimizer/path/joinpath.c:172\u2013186", "paragraphs": []}], "signature": "typedef void (*join_path_setup_hook_type) (PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra);\nextern PGDLLIMPORT join_path_setup_hook_type join_path_setup_hook;", "description": ["Hooks for plugins to get control in set_rel_pathlist()"]}}, "content_hash": "67746ef6ca4087bc7373ece5524de22e2e792f0025d0020c02e0c00e049aa2a8", "imported_at": "2026-09-27T09:57:58.874"}, "snapshot": null, "comparison": {"left": "17", "right": "18", "status": "unchanged", "diff": ""}}