From 84431145af24de7114fc321d27879c030bf04a77 Mon Sep 17 00:00:00 2001 From: Martin Quinteros Date: Wed, 11 Nov 2026 12:26:47 +0000 Subject: [PATCH] [IMP] partner_internal_code: trigram index on internal_code behind a feature flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Create a gin trigram index on unaccent(internal_code) from init(), so ILIKE '%term%' on the field stops scanning the whole table (it is one of the smart search fields of base_name_search_improved) - Use an own index name next to the btree of the field: declaring index="trigram" would make the registry drop the btree and rebuild it as gin without CONCURRENTLY, and the btree serves "=" and the unique check - Only create it when the system parameter saas_feature.partner_search_trigram_index is on, the same flag as the base_ux partner search indexes; it is built on the next -u of the module - Skip creation when pg_trgm is missing or unaccent is not IMMUTABLE - Bump version to 18.0.1.1.0 Change note: Búsqueda de contactos por código interno más rápida en bases con muchos contactos (se habilita por base) X-original-commit: 44d69286d7bd9b4f814e985a512cac2176eed0af --- partner_internal_code/__manifest__.py | 6 +++ partner_internal_code/models/res_partner.py | 50 +++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/partner_internal_code/__manifest__.py b/partner_internal_code/__manifest__.py index 6bf134136..df30bca42 100644 --- a/partner_internal_code/__manifest__.py +++ b/partner_internal_code/__manifest__.py @@ -20,7 +20,13 @@ { "name": "Partner Internal Code", +<<<<<<< d23ecdfac17cc5f16d87b964d9b38718b9981b4b "version": "19.0.1.2.0", +||||||| be9a347cd56daef5a9db4fa64d30d14abaaa567c + "version": "18.0.1.0.0", +======= + "version": "18.0.1.1.0", +>>>>>>> 1df1d9c1bfac5b633022acf6314f7464a2b32ddd "category": "Tools", "sequence": 14, "author": "ADHOC SA", diff --git a/partner_internal_code/models/res_partner.py b/partner_internal_code/models/res_partner.py index 547aa2798..dac3efcae 100644 --- a/partner_internal_code/models/res_partner.py +++ b/partner_internal_code/models/res_partner.py @@ -2,8 +2,22 @@ # For copyright and license notices, see __manifest__.py file in module root # directory ############################################################################## +import logging + from odoo import api, fields, models +<<<<<<< d23ecdfac17cc5f16d87b964d9b38718b9981b4b from odoo.fields import Domain +||||||| be9a347cd56daef5a9db4fa64d30d14abaaa567c +======= +from odoo.modules.db import FunctionStatus +from odoo.tools import create_index + +_logger = logging.getLogger(__name__) + +INTERNAL_CODE_TRIGRAM_INDEX = "res_partner__internal_code_trgm_index" +# Same flag as base_ux partner search indexes; read directly to avoid the dependency. +TRIGRAM_FLAG_PARAM = "saas_feature.partner_search_trigram_index" +>>>>>>> 1df1d9c1bfac5b633022acf6314f7464a2b32ddd class Partner(models.Model): @@ -16,6 +30,7 @@ class Partner(models.Model): "you can also use it to search for the contact.", ) +<<<<<<< d23ecdfac17cc5f16d87b964d9b38718b9981b4b _internal_code_uniq = models.Constraint( "unique (internal_code)", "Internal Code must be unique!", @@ -46,6 +61,41 @@ def name_search(self, name="", domain=None, operator="ilike", limit=100): results = [(partner.id, partner.display_name)] + [res for res in results if res[0] != partner.id] return results[:limit] if limit else results +||||||| be9a347cd56daef5a9db4fa64d30d14abaaa567c +======= + def init(self): + super().init() + self._create_internal_code_trigram_index() + + def _create_internal_code_trigram_index(self): + """Add a gin trigram index for ILIKE on internal_code. + + It goes next to the btree index of the field, with its own name: an + index="trigram" on the field would make the registry drop the btree and + rebuild it as gin without CONCURRENTLY, and the btree is what serves "=". + Only runs when the feature flag is on, so the rollout goes base by base. + """ + flag = self.env["ir.config_parameter"].sudo().get_param(TRIGRAM_FLAG_PARAM, "") + if flag.strip().lower() not in ("1", "true", "yes"): + return + registry = self.env.registry + # Logged at info: a WARNING during install turns the runbot build red. + if not registry.has_trigram: + _logger.info("pg_trgm is missing: %s is not created.", INTERNAL_CODE_TRIGRAM_INDEX) + return + # Without an IMMUTABLE unaccent the index would not match the ORM query. + if registry.has_unaccent != FunctionStatus.INDEXABLE: + _logger.info("unaccent is not indexable: %s is not created.", INTERNAL_CODE_TRIGRAM_INDEX) + return + create_index( + self.env.cr, + indexname=INTERNAL_CODE_TRIGRAM_INDEX, + tablename="res_partner", + expressions=[registry.unaccent('"internal_code"') + " gin_trgm_ops"], + method="gin", + ) + +>>>>>>> 1df1d9c1bfac5b633022acf6314f7464a2b32ddd @api.model_create_multi def create(self, vals_list): for vals in vals_list: