Allow extensions to control join strategy.
At the start of join planning, we build a bitmask called jsa_mask based on
the values of the various enable_* planner GUCs, indicating which join
strategies are allowed. Extensions can override this mask on a plan-wide
basis using join_search_hook, or, generaly more usefully, they can change
the mask for each call to add_paths_to_joinrel using a new hook called
join_path_setup_hook. This is sufficient to allow an extension to force
the use of particular join strategies either in general or for specific
joins, and it is also sufficient to allow an extension to force the join
order.
If you want to control some aspect of planner behavior that is not
join-related, this patch won't help, but the same concepts could be
applied to scans, appendrels, and aggregation.
Notes:
- Materialization and memoization are optional sub-strategies when
performing a nested loop. You might want to avoid these strategies, allow
them, or force them. I don't know how this should be controlled.
- join_path_setup_hook will see JOIN_UNIQUE_INNER or JOIN_UNIQUE_OUTER as the
jointype and can reject if it wants. Conversely, you could allow that
case and reject the JOIN_SEMI/JOIN_RIGHT_SEMI case. However, if you wanted
to force the uniquification to use a sort or a hash rather than the
other, more would be needed (though it looks like you could kludge things
by modifying the SpecialJoinInfo).
- To fully control merge joins produced by sort_outer_and_inner(),
you would need control over which merge clauses are selected.
In match_unsorted_outer(), it's just a function of the input paths.
- You could potentially want to disallow certain strategies at greater
granularity than is possible here - e.g. unparameterized paths aren't
disabled, but making a nested loop out of them is.
- There are going to be residual references to various planner GUCs in
the code path, such as enable_parallel_hash and enable_sort. That seems
fine.
13 files changed: