details: https://code.tryton.org/tryton/commit/96a32b2dc8be
branch: 7.8
user: Cédric Krier <[email protected]>
date: Wed Jul 15 00:26:03 2026 +0200
description:
Define index using COALESCE for nullable Char fields
Closes #14909
(grafted from 525198c97acdd19820d581411b3af0f5bb6e4237)
diffstat:
modules/account/tax.py | 4 ++--
modules/analytic_account/account.py | 2 +-
modules/party/country.py | 5 ++++-
modules/product/product.py | 20 +++++++++++++-------
modules/purchase/product.py | 3 ++-
modules/purchase/purchase.py | 3 ++-
modules/purchase_blanket_agreement/purchase.py | 3 ++-
modules/purchase_request_quotation/purchase.py | 4 ++--
modules/sale/sale.py | 2 +-
modules/sale_blanket_agreement/sale.py | 3 ++-
modules/sale_complaint/complaint.py | 3 ++-
modules/sale_opportunity/opportunity.py | 3 ++-
modules/sale_rental/sale.py | 4 +++-
modules/sale_rental/setup.py | 2 +-
modules/sale_subscription/subscription.py | 2 +-
modules/stock/location.py | 3 ++-
modules/stock/shipment.py | 2 +-
modules/web_user/user.py | 6 ++++--
trytond/trytond/ir/translation.py | 11 +++++++----
trytond/trytond/ir/ui/view.py | 3 ++-
20 files changed, 56 insertions(+), 32 deletions(-)
diffs (396 lines):
diff -r d778a7e8b04c -r 96a32b2dc8be modules/account/tax.py
--- a/modules/account/tax.py Wed Jun 24 22:06:59 2026 +0200
+++ b/modules/account/tax.py Wed Jul 15 00:26:03 2026 +0200
@@ -8,7 +8,7 @@
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 @@
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 -r d778a7e8b04c -r 96a32b2dc8be modules/analytic_account/account.py
--- a/modules/analytic_account/account.py Wed Jun 24 22:06:59 2026 +0200
+++ b/modules/analytic_account/account.py Wed Jul 15 00:26:03 2026 +0200
@@ -99,7 +99,7 @@
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 -r d778a7e8b04c -r 96a32b2dc8be modules/party/country.py
--- a/modules/party/country.py Wed Jun 24 22:06:59 2026 +0200
+++ b/modules/party/country.py Wed Jul 15 00:26:03 2026 +0200
@@ -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 @@
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 -r d778a7e8b04c -r 96a32b2dc8be modules/product/product.py
--- a/modules/product/product.py Wed Jun 24 22:06:59 2026 +0200
+++ b/modules/product/product.py Wed Jul 15 00:26:03 2026 +0200
@@ -201,7 +201,8 @@
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 @@
& (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 -r d778a7e8b04c -r 96a32b2dc8be modules/purchase/product.py
--- a/modules/purchase/product.py Wed Jun 24 22:06:59 2026 +0200
+++ b/modules/purchase/product.py Wed Jul 15 00:26:03 2026 +0200
@@ -5,6 +5,7 @@
from sql import Literal
from sql.aggregate import Count, Max
+from sql.conditionals import Coalesce
from trytond.i18n import gettext
from trytond.model import (
@@ -378,7 +379,7 @@
super().__setup__()
t = cls.__table__()
cls._sql_indexes.update({
- Index(t, (t.code, Index.Similarity())),
+ Index(t, (Coalesce(t.code, ''), Index.Similarity())),
})
@staticmethod
diff -r d778a7e8b04c -r 96a32b2dc8be modules/purchase/purchase.py
--- a/modules/purchase/purchase.py Wed Jun 24 22:06:59 2026 +0200
+++ b/modules/purchase/purchase.py Wed Jul 15 00:26:03 2026 +0200
@@ -8,6 +8,7 @@
from sql import Literal, Null
from sql.aggregate import Count
+from sql.conditionals import Coalesce
from sql.functions import CharLength
from trytond import backend
@@ -267,7 +268,7 @@
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 -r d778a7e8b04c -r 96a32b2dc8be
modules/purchase_blanket_agreement/purchase.py
--- a/modules/purchase_blanket_agreement/purchase.py Wed Jun 24 22:06:59
2026 +0200
+++ b/modules/purchase_blanket_agreement/purchase.py Wed Jul 15 00:26:03
2026 +0200
@@ -6,6 +6,7 @@
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 @@
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 -r d778a7e8b04c -r 96a32b2dc8be
modules/purchase_request_quotation/purchase.py
--- a/modules/purchase_request_quotation/purchase.py Wed Jun 24 22:06:59
2026 +0200
+++ b/modules/purchase_request_quotation/purchase.py Wed Jul 15 00:26:03
2026 +0200
@@ -5,7 +5,7 @@
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 @@
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 -r d778a7e8b04c -r 96a32b2dc8be modules/sale/sale.py
--- a/modules/sale/sale.py Wed Jun 24 22:06:59 2026 +0200
+++ b/modules/sale/sale.py Wed Jul 15 00:26:03 2026 +0200
@@ -336,7 +336,7 @@
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 -r d778a7e8b04c -r 96a32b2dc8be modules/sale_blanket_agreement/sale.py
--- a/modules/sale_blanket_agreement/sale.py Wed Jun 24 22:06:59 2026 +0200
+++ b/modules/sale_blanket_agreement/sale.py Wed Jul 15 00:26:03 2026 +0200
@@ -6,6 +6,7 @@
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 @@
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 -r d778a7e8b04c -r 96a32b2dc8be modules/sale_complaint/complaint.py
--- a/modules/sale_complaint/complaint.py Wed Jun 24 22:06:59 2026 +0200
+++ b/modules/sale_complaint/complaint.py Wed Jul 15 00:26:03 2026 +0200
@@ -6,6 +6,7 @@
from decimal import Decimal
from sql import Null
+from sql.conditionals import Coalesce
from sql.functions import CharLength
from trytond.i18n import gettext
@@ -138,7 +139,7 @@
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 -r d778a7e8b04c -r 96a32b2dc8be modules/sale_opportunity/opportunity.py
--- a/modules/sale_opportunity/opportunity.py Wed Jun 24 22:06:59 2026 +0200
+++ b/modules/sale_opportunity/opportunity.py Wed Jul 15 00:26:03 2026 +0200
@@ -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 @@
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 -r d778a7e8b04c -r 96a32b2dc8be modules/sale_rental/sale.py
--- a/modules/sale_rental/sale.py Wed Jun 24 22:06:59 2026 +0200
+++ b/modules/sale_rental/sale.py Wed Jul 15 00:26:03 2026 +0200
@@ -5,6 +5,8 @@
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 @@
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 -r d778a7e8b04c -r 96a32b2dc8be modules/sale_rental/setup.py
--- a/modules/sale_rental/setup.py Wed Jun 24 22:06:59 2026 +0200
+++ b/modules/sale_rental/setup.py Wed Jul 15 00:26:03 2026 +0200
@@ -44,7 +44,7 @@
download_url = 'http://downloads.tryton.org/%s.%s/' % (
major_version, minor_version)
-requires = []
+requires = ['python-sql']
for dep in info.get('depends', []):
if not re.match(r'(ir|res)(\W|$)', dep):
requires.append(get_require_version('trytond_%s' % dep))
diff -r d778a7e8b04c -r 96a32b2dc8be modules/sale_subscription/subscription.py
--- a/modules/sale_subscription/subscription.py Wed Jun 24 22:06:59 2026 +0200
+++ b/modules/sale_subscription/subscription.py Wed Jul 15 00:26:03 2026 +0200
@@ -172,7 +172,7 @@
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 -r d778a7e8b04c -r 96a32b2dc8be modules/stock/location.py
--- a/modules/stock/location.py Wed Jun 24 22:06:59 2026 +0200
+++ b/modules/stock/location.py Wed Jul 15 00:26:03 2026 +0200
@@ -5,6 +5,7 @@
from decimal import Decimal
from sql import Column
+from sql.conditionals import Coalesce
from trytond.cache import Cache
from trytond.i18n import gettext
@@ -198,7 +199,7 @@
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 -r d778a7e8b04c -r 96a32b2dc8be modules/stock/shipment.py
--- a/modules/stock/shipment.py Wed Jun 24 22:06:59 2026 +0200
+++ b/modules/stock/shipment.py Wed Jul 15 00:26:03 2026 +0200
@@ -66,7 +66,7 @@
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 -r d778a7e8b04c -r 96a32b2dc8be modules/web_user/user.py
--- a/modules/web_user/user.py Wed Jun 24 22:06:59 2026 +0200
+++ b/modules/web_user/user.py Wed Jul 15 00:26:03 2026 +0200
@@ -89,10 +89,12 @@
]
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 -r d778a7e8b04c -r 96a32b2dc8be trytond/trytond/ir/translation.py
--- a/trytond/trytond/ir/translation.py Wed Jun 24 22:06:59 2026 +0200
+++ b/trytond/trytond/ir/translation.py Wed Jul 15 00:26:03 2026 +0200
@@ -12,7 +12,7 @@
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
import trytond.config as config
@@ -112,9 +112,11 @@
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')),
@@ -122,7 +124,8 @@
(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 -r d778a7e8b04c -r 96a32b2dc8be trytond/trytond/ir/ui/view.py
--- a/trytond/trytond/ir/ui/view.py Wed Jun 24 22:06:59 2026 +0200
+++ b/trytond/trytond/ir/ui/view.py Wed Jul 15 00:26:03 2026 +0200
@@ -5,6 +5,7 @@
from lxml import etree
from sql import Literal, Null
+from sql.conditionals import Coalesce
from trytond.cache import Cache, MemoryCache
from trytond.i18n import gettext
@@ -726,7 +727,7 @@
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