diff --git a/modules/account/tax.py b/modules/account/tax.py index db2055893e..a5ece0f2f7 100644 --- a/modules/account/tax.py +++ b/modules/account/tax.py @@ -8,7 +8,7 @@ from itertools import cycle, groupby from sql import Literal from sql.aggregate import Sum -from sql.conditionals import Case +from sql.conditionals import Case, Coalesce from trytond import backend from trytond.i18n import gettext @@ -164,7 +164,7 @@ class TaxCode( super().__setup__() t = cls.__table__() cls._sql_indexes.add( - Index(t, (t.code, Index.Similarity()))) + Index(t, (Coalesce(t.code, ''), Index.Similarity()))) for date in [cls.start_date, cls.end_date]: date.states = { 'readonly': (Bool(Eval('template', -1)) diff --git a/modules/analytic_account/account.py b/modules/analytic_account/account.py index ff82b58ca8..c7360a4704 100644 --- a/modules/analytic_account/account.py +++ b/modules/analytic_account/account.py @@ -98,7 +98,7 @@ class Account( super().__setup__() t = cls.__table__() cls._sql_indexes.add( - Index(t, (t.code, Index.Similarity()))) + Index(t, (Coalesce(t.code, ''), Index.Similarity()))) cls._order.insert(0, ('code', 'ASC')) cls._order.insert(1, ('name', 'ASC')) diff --git a/modules/party/country.py b/modules/party/country.py index fcd97fa173..b17bce122e 100644 --- a/modules/party/country.py +++ b/modules/party/country.py @@ -1,6 +1,8 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. +from sql.conditionals import Coalesce + from trytond.model import Index from trytond.pool import PoolMeta @@ -15,7 +17,8 @@ class PostalCode(metaclass=PoolMeta): cls._sql_indexes.update({ Index( t, - (Index.Unaccent(t.city), Index.Similarity()), + (Index.Unaccent(Coalesce(t.city, '')), + Index.Similarity()), (t.country, Index.Range()), (t.subdivision, Index.Range())), }) diff --git a/modules/product/product.py b/modules/product/product.py index e1b46c02c1..ad2a4733ea 100644 --- a/modules/product/product.py +++ b/modules/product/product.py @@ -201,7 +201,8 @@ class Template( super().__setup__() t = cls.__table__() cls._sql_indexes.update({ - Index(t, (t.code, Index.Similarity())), + Index(t, (Coalesce(t.code, ''), Index.Equality())), + Index(t, (Coalesce(t.code, ''), Index.Similarity())), }) cls._order.insert(0, ('rec_name', 'ASC')) @@ -587,12 +588,17 @@ class Product( & (t.code != '')), 'product.msg_product_code_unique'), ] - cls._sql_indexes.add( - Index(t, (t.code, Index.Similarity(cardinality='high')))) - cls._sql_indexes.add( - Index(t, - (t.position, Index.Range(order='ASC NULLS FIRST')), - (t.id, Index.Range(order='ASC')))) + cls._sql_indexes.update({ + Index(t, + (Coalesce(t.code, ''), + Index.Equality(cardinality='high'))), + Index(t, + (Coalesce(t.code, ''), + Index.Similarity(cardinality='high'))), + Index(t, + (t.position, Index.Range(order='ASC NULLS FIRST')), + (t.id, Index.Range(order='ASC'))), + }) for attr in dir(Template): tfield = getattr(Template, attr) diff --git a/modules/project/work.py b/modules/project/work.py index c7ec1898e9..ccca777ac2 100644 --- a/modules/project/work.py +++ b/modules/project/work.py @@ -5,6 +5,7 @@ import datetime from collections import defaultdict from sql import Null +from sql.conditionals import Coalesce from sql.functions import CharLength from trytond.cache import Cache @@ -257,9 +258,13 @@ class Work( 'project.msg_work_number_unique'), ] cls._sql_indexes.update({ - Index(t, (t.number, Index.Equality(cardinality='high'))), - Index(t, (t.number, Index.Similarity(cardinality='high'))), - Index(t, (t.path, Index.Similarity(begin=True))), + Index(t, + (Coalesce(t.number, ''), + Index.Equality(cardinality='high'))), + Index(t, + (Coalesce(t.number, ''), + Index.Similarity(cardinality='high'))), + Index(t, (Coalesce(t.path, ''), Index.Similarity(begin=True))), }) @classmethod diff --git a/modules/purchase/product.py b/modules/purchase/product.py index 34cfe29ca7..c0be2f9720 100644 --- a/modules/purchase/product.py +++ b/modules/purchase/product.py @@ -4,6 +4,7 @@ import datetime from collections import defaultdict from sql.aggregate import Count, Max +from sql.conditionals import Coalesce from trytond.i18n import gettext from trytond.model import ( @@ -324,7 +325,7 @@ class ProductSupplier( super().__setup__() t = cls.__table__() cls._sql_indexes.update({ - Index(t, (t.code, Index.Similarity())), + Index(t, (Coalesce(t.code, ''), Index.Similarity())), }) @staticmethod diff --git a/modules/purchase/purchase.py b/modules/purchase/purchase.py index 2719f0334f..0c073abd0c 100644 --- a/modules/purchase/purchase.py +++ b/modules/purchase/purchase.py @@ -8,6 +8,7 @@ from itertools import chain, groupby from sql import Null from sql.aggregate import Count +from sql.conditionals import Coalesce from sql.functions import CharLength from trytond import backend @@ -269,7 +270,7 @@ class Purchase( super().__setup__() t = cls.__table__() cls._sql_indexes.update({ - Index(t, (t.reference, Index.Similarity())), + Index(t, (Coalesce(t.reference, ''), Index.Similarity())), Index(t, (t.party, Index.Range())), Index( t, diff --git a/modules/purchase_blanket_agreement/purchase.py b/modules/purchase_blanket_agreement/purchase.py index 05ec3ff9f7..91abc9ff37 100644 --- a/modules/purchase_blanket_agreement/purchase.py +++ b/modules/purchase_blanket_agreement/purchase.py @@ -6,6 +6,7 @@ from decimal import Decimal from itertools import groupby from sql import Null +from sql.conditionals import Coalesce from sql.functions import CharLength from trytond.i18n import gettext @@ -192,7 +193,7 @@ class BlanketAgreement(Workflow, ModelSQL, ModelView, ChatMixin): super().__setup__() t = cls.__table__() cls._sql_indexes.update({ - Index(t, (t.reference, Index.Similarity())), + Index(t, (Coalesce(t.reference, ''), Index.Similarity())), Index( t, (t.state, Index.Equality(cardinality='low')), where=t.state.in_(['draft', 'running'])), diff --git a/modules/purchase_request_quotation/purchase.py b/modules/purchase_request_quotation/purchase.py index d516d4a736..6b35ec3c92 100644 --- a/modules/purchase_request_quotation/purchase.py +++ b/modules/purchase_request_quotation/purchase.py @@ -5,7 +5,7 @@ from functools import wraps from itertools import groupby from sql import Null -from sql.conditionals import Case +from sql.conditionals import Case, Coalesce from sql.functions import CharLength from trytond.i18n import gettext @@ -140,7 +140,7 @@ class Quotation(Workflow, ModelSQL, ModelView, ChatMixin): super().__setup__() t = cls.__table__() cls._sql_indexes.update({ - Index(t, (t.reference, Index.Similarity())), + Index(t, (Coalesce(t.reference, ''), Index.Similarity())), Index( t, (t.state, Index.Equality(cardinality='low')), where=t.state.in_(['draft', 'sent'])), diff --git a/modules/quality/quality.py b/modules/quality/quality.py index 53eedb6468..46f71869e1 100644 --- a/modules/quality/quality.py +++ b/modules/quality/quality.py @@ -5,6 +5,7 @@ import datetime as dt from functools import wraps from random import Random +from sql.conditionals import Coalesce from sql.functions import CharLength from trytond.i18n import gettext, lazy_gettext @@ -412,7 +413,7 @@ class Inspection(Workflow, ModelSQL, ModelView, ChatMixin): super().__setup__() t = cls.__table__() cls._sql_indexes.update({ - Index(t, (t.reference, Index.Similarity())), + Index(t, (Coalesce(t.reference, ''), Index.Similarity())), }) cls._transitions |= { ('pending', 'passed'), diff --git a/modules/sale/sale.py b/modules/sale/sale.py index c0b753a317..9688dc9302 100644 --- a/modules/sale/sale.py +++ b/modules/sale/sale.py @@ -338,7 +338,7 @@ class Sale( super().__setup__() t = cls.__table__() cls._sql_indexes.update({ - Index(t, (t.reference, Index.Similarity())), + Index(t, (Coalesce(t.reference, ''), Index.Similarity())), Index(t, (t.party, Index.Range())), Index( t, diff --git a/modules/sale_blanket_agreement/sale.py b/modules/sale_blanket_agreement/sale.py index ba43d104b5..235caa12af 100644 --- a/modules/sale_blanket_agreement/sale.py +++ b/modules/sale_blanket_agreement/sale.py @@ -6,6 +6,7 @@ from decimal import Decimal from itertools import groupby from sql import Null +from sql.conditionals import Coalesce from sql.functions import CharLength from trytond.i18n import gettext @@ -192,7 +193,7 @@ class BlanketAgreement(Workflow, ModelSQL, ModelView, ChatMixin): super().__setup__() t = cls.__table__() cls._sql_indexes.update({ - Index(t, (t.reference, Index.Similarity())), + Index(t, (Coalesce(t.reference, ''), Index.Similarity())), Index( t, (t.state, Index.Equality(cardinality='low')), where=t.state.in_(['draft', 'running'])), diff --git a/modules/sale_complaint/complaint.py b/modules/sale_complaint/complaint.py index ac7c301536..fcd573ca68 100644 --- a/modules/sale_complaint/complaint.py +++ b/modules/sale_complaint/complaint.py @@ -6,6 +6,7 @@ from collections import defaultdict from decimal import Decimal from sql import Null +from sql.conditionals import Coalesce from sql.functions import CharLength from trytond import backend @@ -139,7 +140,7 @@ class Complaint(Workflow, ModelSQL, ModelView, ChatMixin): super().__setup__() t = cls.__table__() cls._sql_indexes.update({ - Index(t, (t.reference, Index.Similarity())), + Index(t, (Coalesce(t.reference, ''), Index.Similarity())), Index( t, (t.state, Index.Equality(cardinality='low')), diff --git a/modules/sale_opportunity/opportunity.py b/modules/sale_opportunity/opportunity.py index bb90d51a2b..8ddb54d785 100644 --- a/modules/sale_opportunity/opportunity.py +++ b/modules/sale_opportunity/opportunity.py @@ -4,6 +4,7 @@ import datetime from itertools import groupby +from sql.conditionals import Coalesce from sql.functions import CharLength from trytond.i18n import gettext @@ -154,7 +155,7 @@ class SaleOpportunity( super().__setup__() t = cls.__table__() cls._sql_indexes.update({ - Index(t, (t.reference, Index.Similarity())), + Index(t, (Coalesce(t.reference, ''), Index.Similarity())), Index(t, (t.party, Index.Range())), Index( t, diff --git a/modules/sale_rental/pyproject.toml b/modules/sale_rental/pyproject.toml index 1da4d7d98c..fd4beaa52d 100644 --- a/modules/sale_rental/pyproject.toml +++ b/modules/sale_rental/pyproject.toml @@ -52,7 +52,7 @@ exclude = ['doc'] "" = "trytond/modules/sale_rental" [tool.hatch.metadata.hooks.tryton] -dependencies = [] +dependencies = ['python-sql'] copyright = 'COPYRIGHT' readme = 'README.rst' diff --git a/modules/sale_rental/sale.py b/modules/sale_rental/sale.py index 82d73d84a6..b518fc0628 100644 --- a/modules/sale_rental/sale.py +++ b/modules/sale_rental/sale.py @@ -5,6 +5,8 @@ import datetime as dt from decimal import Decimal from functools import partial +from sql.conditionals import Coalesce + from trytond.i18n import gettext from trytond.ir.attachment import AttachmentCopyMixin from trytond.ir.note import NoteCopyMixin @@ -277,7 +279,7 @@ class Rental( super().__setup__() t = cls.__table__() cls._sql_indexes.update({ - Index(t, (t.reference, Index.Similarity())), + Index(t, (Coalesce(t.reference, ''), Index.Similarity())), Index(t, (t.party, Index.Equality())), Index( t, diff --git a/modules/sale_subscription/subscription.py b/modules/sale_subscription/subscription.py index 52f49dc039..90c3b2a88f 100644 --- a/modules/sale_subscription/subscription.py +++ b/modules/sale_subscription/subscription.py @@ -172,7 +172,7 @@ class Subscription(Workflow, ModelSQL, ModelView, ChatMixin): super().__setup__() t = cls.__table__() cls._sql_indexes.update({ - Index(t, (t.reference, Index.Similarity())), + Index(t, (Coalesce(t.reference, ''), Index.Similarity())), Index( t, (t.state, Index.Equality(cardinality='low')), diff --git a/modules/stock/location.py b/modules/stock/location.py index 939f1dc3bd..483328762c 100644 --- a/modules/stock/location.py +++ b/modules/stock/location.py @@ -5,6 +5,7 @@ import operator from decimal import Decimal from sql import Column +from sql.conditionals import Coalesce from trytond.cache import Cache from trytond.i18n import gettext @@ -197,7 +198,7 @@ class Location(DeactivableMixin, tree(), ModelSQL, ModelView): super().__setup__() t = cls.__table__() cls._sql_indexes.update({ - Index(t, (t.code, Index.Similarity())), + Index(t, (Coalesce(t.code, ''), Index.Similarity())), Index( t, (t.left, Index.Range(cardinality='high')), diff --git a/modules/stock/shipment.py b/modules/stock/shipment.py index 4ed67113a5..0118ffaec8 100644 --- a/modules/stock/shipment.py +++ b/modules/stock/shipment.py @@ -66,7 +66,7 @@ class ShipmentMixin: super().__setup__() t = cls.__table__() cls._sql_indexes.update({ - Index(t, (t.reference, Index.Similarity())), + Index(t, (Coalesce(t.reference, ''), Index.Similarity())), }) cls._order = [ ('effective_date', 'ASC NULLS LAST'), diff --git a/modules/web_user/user.py b/modules/web_user/user.py index ecc98632a3..62b8d3b04a 100644 --- a/modules/web_user/user.py +++ b/modules/web_user/user.py @@ -89,10 +89,12 @@ class User(avatar_mixin(100), DeactivableMixin, ModelSQL, ModelView): ] cls._sql_indexes.update({ Index( - table, (table.email, Index.Equality(cardinality='high'))), + table, (Coalesce(table.email, ''), + Index.Equality(cardinality='high'))), Index( table, - (table.email_token, Index.Equality(cardinality='high')), + (Coalesce(table.email_token, ''), + Index.Equality(cardinality='high')), where=table.email_token != Null), }) cls._buttons.update({ diff --git a/trytond/trytond/ir/translation.py b/trytond/trytond/ir/translation.py index 730027ffeb..13c8490fb8 100644 --- a/trytond/trytond/ir/translation.py +++ b/trytond/trytond/ir/translation.py @@ -12,7 +12,7 @@ from relatorio.reporting import MIMETemplateLoader from relatorio.templates.opendocument import get_zip_file from sql import Column, Literal, Null from sql.aggregate import Max -from sql.conditionals import Case +from sql.conditionals import Case, Coalesce from sql.functions import CharLength, Position, Substring from sql.operators import Concat @@ -120,9 +120,11 @@ class Translation( cls._sql_indexes.update({ Index( - table, (Index.Unaccent(table.src), Index.Similarity())), + table, (Index.Unaccent(Coalesce(table.src, '')), + Index.Similarity())), Index( - table, (Index.Unaccent(table.value), Index.Similarity())), + table, (Index.Unaccent(Coalesce(table.value, '')), + Index.Similarity())), Index( table, (table.type, Index.Equality(cardinality='low')), @@ -130,7 +132,8 @@ class Translation( (table.lang, Index.Equality(cardinality='low')), (table.res_id, Index.Range()), (table.fuzzy, Index.Equality(cardinality='low')), - (Index.Unaccent(table.value), Index.Similarity())), + (Index.Unaccent(Coalesce(table.value, '')), + Index.Similarity())), Index( table, (table.type, Index.Equality(cardinality='low')), diff --git a/trytond/trytond/ir/ui/view.py b/trytond/trytond/ir/ui/view.py index 76d2028a01..45aba9b029 100644 --- a/trytond/trytond/ir/ui/view.py +++ b/trytond/trytond/ir/ui/view.py @@ -788,7 +788,7 @@ class ViewTreeState( table, (table.user, Index.Range()), (table.model, Index.Equality()), - (table.child_name, Index.Equality()), + (Coalesce(table.child_name, ''), Index.Equality()), (table.domain, Index.Equality()))) @staticmethod