diff --git a/CHANGELOG b/CHANGELOG index 9ad08464eb..528e3be317 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Add sql_id method to Reference field * Use declarative index definition for ModelSQL * Add configuration entries for unaccent and similarity functions * Add authentication services diff --git a/doc/ref/fields.rst b/doc/ref/fields.rst index b2c1a9fe07..0cfd87e6d1 100644 --- a/doc/ref/fields.rst +++ b/doc/ref/fields.rst @@ -684,6 +684,10 @@ Instance methods: Same as :meth:`~Selection.translated` but for the translated name of the target model. +.. method:: Reference.sql_id(column, Model) + + Return the SQL expression that extract the record ID of the column. + Many2One -------- diff --git a/trytond/model/fields/many2many.py b/trytond/model/fields/many2many.py index 54ccf3c0c3..b3e66e04f6 100644 --- a/trytond/model/fields/many2many.py +++ b/trytond/model/fields/many2many.py @@ -3,9 +3,8 @@ from collections import defaultdict from itertools import chain -from sql import Cast, Literal, Null +from sql import Literal, Null from sql.conditionals import Coalesce -from sql.functions import Position, Substring from trytond.pool import Pool from trytond.pyson import PYSONEncoder @@ -379,9 +378,7 @@ class Many2Many(Field): origin_where = None if origin_field._type == 'reference': origin_where = origin.like(Model.__name__ + ',%') - origin = Cast(Substring(origin, - Position(',', origin) + Literal(1)), - Relation.id.sql_type().base) + origin = origin_field.sql_id(origin, Relation) target = getattr(Relation, self.target).sql_column(relation) if '.' not in name: diff --git a/trytond/model/fields/one2many.py b/trytond/model/fields/one2many.py index 1f8604163e..711202988f 100644 --- a/trytond/model/fields/one2many.py +++ b/trytond/model/fields/one2many.py @@ -3,9 +3,7 @@ from collections import defaultdict from itertools import chain -from sql import Cast, Literal from sql.conditionals import Coalesce -from sql.functions import Position, Substring from trytond.pool import Pool from trytond.pyson import PYSONEncoder @@ -332,9 +330,7 @@ class One2Many(Field): origin_where = None if origin_field._type == 'reference': origin_where = origin.like(Model.__name__ + ',%') - origin = Cast(Substring(origin, - Position(',', origin) + Literal(1)), - Target.id.sql_type().base) + origin = origin_field.sql_id(origin, Target) if '.' not in name: if value is None: diff --git a/trytond/model/fields/reference.py b/trytond/model/fields/reference.py index 33b44569fb..2aa9c6a96e 100644 --- a/trytond/model/fields/reference.py +++ b/trytond/model/fields/reference.py @@ -187,6 +187,12 @@ class Reference(SelectionMixin, Field): value = str(value) return super(Reference, self).sql_format(value) + def sql_id(self, column, Model): + "Return SQL expression for the id part of the field" + return Cast(Substring( + column, Position(',', column) + Literal(1)), + Model.id.sql_type().base) + @with_inactive_records def convert_domain(self, domain, tables, Model): if '.' not in domain[0]: @@ -203,9 +209,8 @@ class Reference(SelectionMixin, Field): if 'active' in Target._fields: target_domain.append(('active', 'in', [True, False])) query = Target.search(target_domain, order=[], query=True) - return (Cast(Substring(column, - Position(',', column) + Literal(1)), - Model.id.sql_type().base).in_(query) + return ( + self.sql_id(column, Model).in_(query) & column.like(target + ',%')) def definition(self, model, language): diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index 66bc79f18e..18687fcead 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -318,6 +318,8 @@ class ModelSQL(ModelStorage): Index( target, (column, Index.Similarity(begin=True)), + (target_field.sql_id(column, Target), + Index.Range()), where=where), }) else: