Many2one LEFT JOINs promoted to INNER JOINs
The ORM now adds a hint that lets PostgreSQL turn LEFT JOINs on optional many2one fields into INNER JOINs for positive conditions. This gives the query planner more join orders to choose from.
The ORM now adds a hint that lets PostgreSQL turn LEFT JOINs on optional many2one fields into INNER JOINs for positive conditions. This gives the query planner more join orders to choose from.
| Branch | Pull request | Commit |
|---|---|---|
| 19.0 | odoo/odoo#287712 ↗ | dfc5e84ec8 ↗ |
[PERF] orm: add explicit JOIN-promotion hint for many2one LEFT JOINs Odoo uses a LEFT JOIN when traversing an optional many2one field, since the FK can be unset. For positive conditions, the SQL already included `fk_col IS NOT NULL` to exclude records where the relation is empty, which logically makes the LEFT JOIN equivalent to an INNER JOIN, but does not trigger PostgreSQL's join promotion. To decide whether to promote, PostgreSQL scans the WHERE clause for predicates that cannot return TRUE when the right-side table's columns are all NULL (as they would be on an unmatched row). `fk_col IS NOT NULL` is a predicate on the left table, so it is invisible to that check. Table constraints do not help either: the promotion logic (`reduce_outer_joins()`) is purely predicate-based and does not consult them. Adding `joined_table.id IS NOT NULL` gives the planner exactly what it needs: a null-rejecting predicate on the right side. Once promoted to an INNER JOIN, the planner can reorder the join freely, typically choosing to start from the smaller lookup table rather than being forced to drive from the large fact table and discard most rows afterward. The predicate is a semantic no-op and acts purely as a hint: if the join matched, the right-side `id` is by definition not NULL, so query results are identical and there is no behavioral risk. The `fk_col IS NOT NULL` is kept, even if there is an equivalence class between the `id` and the `fk_col` post-promotion, because PG doesn't evaluate cost estimation with equivalence class evaluated, only based on the initial predicate on the table. This is impactful if the `fk_col` predicate is highly selective. task-6296255