Skip to content

[IMP] base_search_fuzzy - add support of translatable fields - #3429

Merged
OCA-git-bot merged 1 commit into
OCA:18.0from
yvaucher:18-fuzzy-translatable
Jun 5, 2026
Merged

[IMP] base_search_fuzzy - add support of translatable fields#3429
OCA-git-bot merged 1 commit into
OCA:18.0from
yvaucher:18-fuzzy-translatable

Conversation

@yvaucher

Copy link
Copy Markdown
Member

depends on:

This allow to create a trigram index on translatable fields.

Searches on translatable fields look like this:

SELECT * FROM table WHERE COALESCE({column_name}->>'{lang}', {column_name}->>'en_US' % 'text'

On a DB with 8M dummy products (duplicated with odoo populate),

With a query containing

WHERE COALESCE("product_template"."name"->>'fr_FR', "product_template"."name"->>'en_US') % 'search text')

Without index
Execution Time: 10606.619 ms

With index:
Execution Time: 484.383 ms

⚠️ For en_US to work with operator % this requires a patch on the core odoo/odoo#232993

@yvaucher
yvaucher force-pushed the 18-fuzzy-translatable branch from f8cfea5 to d7f9d2e Compare October 24, 2025 14:27
Comment thread base_search_fuzzy/models/trgm_index.py Outdated
Comment thread base_search_fuzzy/views/trgm_index.xml Outdated
@yvaucher
yvaucher force-pushed the 18-fuzzy-translatable branch from d7f9d2e to 8c2bb35 Compare October 26, 2025 15:05
@yvaucher
yvaucher force-pushed the 18-fuzzy-translatable branch from 8c2bb35 to e8c0b1a Compare October 26, 2025 15:09
@yvaucher

Copy link
Copy Markdown
Member Author

@sbidoul Thanks for the review, I made the fixes following your remarks.

@pedrobaeza pedrobaeza left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/ocabot merge major

@OCA-git-bot

Copy link
Copy Markdown
Contributor

Hey, thanks for contributing! Proceeding to merge this for you.
Prepared branch 18.0-ocabot-merge-pr-3429-by-pedrobaeza-bump-major, awaiting test results.

@OCA-git-bot
OCA-git-bot merged commit 79424c9 into OCA:18.0 Jun 5, 2026
5 of 7 checks passed
@OCA-git-bot

Copy link
Copy Markdown
Contributor

Congratulations, your PR was merged at bca1713. Thanks a lot for contributing to OCA. ❤️

dnplkndll added a commit to ledoent/server-tools that referenced this pull request Jun 11, 2026
The `%` similarity predicate now renders as `(<field>) %% <value>`.

A translatable field renders in SQL as the bare JSON accessor
`name->>'en_US'` (core's BaseString.to_sql does not wrap the
single-language case). `%` binds tighter than `->>`, so the previous
`name->>'en_US' %% 'foo'` parsed as `name->>('en_US' %% 'foo')` and
failed with "operator does not exist: jsonb ->> boolean". The 18.0
module relies on the still-unmerged core PR odoo/odoo#232993 to add
this wrapping; on 19.0 the operator is emitted by this module's own
Domain.custom, so we parenthesize here instead and carry no core
dependency.

The parentheses also make the predicate match the parenthesized
expression index that trgm_index builds for translatable columns
(`(name->>'en_US')` / `COALESCE(name->>'lang', name->>'en_US')`),
introduced by the translatable-fields support picked from OCA#3429.

Exact-SQL test assertions updated to the parenthesized form.
dnplkndll added a commit to ledoent/server-tools that referenced this pull request Jun 11, 2026
Re-implements the PostgreSQL trigram similarity operator ``%`` using
Odoo 19's ``@operator_optimization`` decorator + ``Domain.custom``.

The 18.0 ``post_load`` hook that mutated
``odoo.osv.expression.TERM_OPERATORS`` and ``SQL_OPERATORS`` no longer
works in 19.0:

- ``SQL_OPERATORS`` moved from ``odoo.osv.expression`` to
  ``odoo.orm.utils`` (no re-export).
- ``TERM_OPERATORS`` is now a rebound copy of
  ``odoo.orm.domains.CONDITION_OPERATORS``; the new ``Domain``
  validator keys off ``CONDITION_OPERATORS`` directly, so mutating
  ``expression.TERM_OPERATORS`` no longer registers the operator.
- The new generic ``Field._condition_to_sql`` does not consult
  ``SQL_OPERATORS`` for unknown operators; an unknown operator like
  ``%`` raises ``NotImplementedError``.

The replacement registers the operator at import time via
``@operator_optimization(['%'])`` and emits the trigram-similarity
predicate through ``Domain.custom(to_sql=...)`` — the supported path
used in core by ``auth_totp``, ``analytic_mixin`` and
``account_tax``. ``post_load`` is dropped from the manifest, and
``hooks.py`` is removed.

Tests assert ``%`` is in ``CONDITION_OPERATORS`` and verify the
emitted SQL contains the field reference + escaped ``%%`` template;
the end-to-end ``pg_trgm`` test is unchanged.

Adaptations to the translatable-fields trigram support (OCA#3429,
merged into 18.0 and replayed above):

- The `%` predicate is emitted as `(<field>) %% <value>`: a
  translatable field renders as the bare JSON accessor
  `name->>'en_US'`, and `%` binds tighter than `->>`, so the
  unparenthesized form fails with "operator does not exist:
  jsonb ->> boolean". On 18.0 that wrapping comes from the still-open
  odoo/odoo#232993; here the operator is emitted by this module's own
  Domain.custom, so the parentheses make 19.0 self-contained.
- The generated translatable index name is folded to lowercase:
  CREATE INDEX folds the unquoted identifier, but get_not_used_index
  compares it literally against pg_indexes, so the mixed-case lang
  component never matched.
- New end-to-end test: trgm.index creation on a translatable field
  verified against pg_indexes, then an actual `%` search in lang
  context. The index-collision test no longer reuses an index name
  the module's demo data takes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants