fixup! Allow for plugin control over path generation strategies.
authorRobert Haas <[email protected]>
Wed, 10 Dec 2025 19:05:16 +0000 (14:05 -0500)
committerRobert Haas <[email protected]>
Wed, 10 Dec 2025 19:10:48 +0000 (14:10 -0500)
Move the call to join_path_setup_hook earlier so that it can see
unique inner/outer joins, and improve the comment.

src/backend/optimizer/path/joinpath.c

index 388d8456ff63fb2e947b32a91846dd9fda5f3f48..82dab3d60047bfd7b4b6451491c7fb4df3fcfbb2 100644 (file)
@@ -154,6 +154,32 @@ add_paths_to_joinrel(PlannerInfo *root,
        extra.param_source_rels = NULL;
        extra.pgs_mask = joinrel->pgs_mask;
 
+       /*
+        * 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.
+        */
+       if (join_path_setup_hook)
+               join_path_setup_hook(root, joinrel, outerrel, innerrel,
+                                                        jointype, &extra);
+
        /*
         * See if the inner relation is provably unique for this outer rel.
         *
@@ -209,31 +235,6 @@ add_paths_to_joinrel(PlannerInfo *root,
        if (jointype == JOIN_UNIQUE_OUTER || jointype == JOIN_UNIQUE_INNER)
                jointype = JOIN_INNER;
 
-       /*
-        * 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 = 0, 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
-        * even replace the mask entirely.
-        *
-        * 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.
-        */
-       if (join_path_setup_hook)
-               join_path_setup_hook(root, joinrel, outerrel, innerrel,
-                                                        jointype, &extra);
-
        /*
         * Find potential mergejoin clauses.  We can skip this if we are not
         * interested in doing a mergejoin.  However, mergejoin may be our only