[IMP] core: add unaccent to trigram indexes

We added trigram index for char fields since https://github.com/odoo/odoo/pull/83015.
But if `unaccent` is installed in the database (and isn't force to
`False` on field), these new trigram indexes are pointless and cost a
lot for nothing (almost nothing, it still can be used for equality
operator but in this case a btree will be far more efficient).

The simple way to fix it is to add `unaccent(<column>)` in the index
trigram definition, but unfortunately `unaccent` is not immutable and
may therefore not be indexed.  In order to make `unaccent` indexable, we
must declare it as immutable (see
https://stackoverflow.com/questions/11005036/does-postgresql-support-accent-insensitive-collations/11007216#11007216
for more information and how to do that).

With this patch, trigram indexes are created with `unaccent(<column>)`
if the function `unaccent` is available in the database, and for the
fields that are not declared with `unaccent=False`.  Moreover, we issue
a warning when `unaccent` is available but is not immutable, in which
case most trigram indexes will be useless.

odoo/upgrade#3736
task-2551518

closes odoo/odoo#95943

Signed-off-by: Rémy Voet <ryv@odoo.com>
This commit is contained in:
Rémy Voet (ryv)
2022-09-05 18:34:53 +02:00
parent 7f0f7bcdce
commit 4087bcdc5e
5 changed files with 62 additions and 41 deletions
-20
View File
@@ -234,26 +234,6 @@ def fix_foreign_key(cr, tablename1, columnname1, tablename2, columnname2, ondele
if not found:
return add_foreign_key(cr, tablename1, columnname1, tablename2, columnname2, ondelete)
def install_pg_trgm(cr):
cr.execute("SELECT installed_version FROM pg_available_extensions WHERE name='pg_trgm'")
version = cr.fetchone()
if version is None:
return False
if version[0]:
return True
cr.execute('SELECT usesuper FROM pg_user WHERE usename = CURRENT_USER')
if not cr.fetchone()[0]:
return False
try:
db = odoo.sql_db.db_connect(cr.dbname)
with closing(db.cursor()) as cr:
cr.execute("CREATE EXTENSION IF NOT EXISTS pg_trgm")
cr.commit()
return True
except psycopg2.Error:
return False
def index_exists(cr, indexname):
""" Return whether the given index exists. """
cr.execute("SELECT 1 FROM pg_indexes WHERE indexname=%s", (indexname,))