Files
tryton/trytond/model/fields/text.py
T
Cédric Krier 123757907c Do not order on NULL when rank column is None
It is not valid to use NULL in ORDER BY clause.

issue10947
review381411002
(grafted from 449158110f20a1cb2d96d140c7e9b91ba95bbe1f)

--HG--
branch : 6.0
2021-11-19 23:56:36 +01:00

96 lines
3.3 KiB
Python

# 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 import Query, Expression, Null, Literal
from sql.operators import ILike, Not, In, NotIn
from trytond.transaction import Transaction
from .field import Field, SQL_OPERATORS
from .char import Char
class Text(Char):
'''
Define a text field (``unicode``).
'''
_type = 'text'
_sql_type = 'TEXT'
forbidden_chars = ''
search_full_text = True
class FullText(Field):
'''
Define a full text field.
'''
_type = 'full_text'
_sql_type = 'FULLTEXT'
_py_type = str
def sql_format(self, value):
if isinstance(value, (Query, Expression)):
return value
if not value:
return Null
if isinstance(value, (int, float)):
return value
transaction = Transaction()
database = transaction.database
if isinstance(value, str):
value = [value]
return database.format_full_text(*value, language=transaction.language)
def _rank_column(self, column, name, Model):
transaction = Transaction()
context = transaction.context
database = transaction.database
key = '%s.%s.order' % (Model.__name__, name)
value = context.get(key)
if value and database.has_search_full_text():
value = database.format_full_text_query(
value, language=transaction.language)
return database.rank_full_text(column, value, normalize=['rank'])
def convert_domain(self, domain, tables, Model):
transaction = Transaction()
database = transaction.database
table, _ = tables[None]
name, operator, value = domain
assert name == self.name
column = self.sql_column(table)
column = self._domain_column(operator, column)
if operator.endswith('like'):
if database.has_search_full_text():
value = database.format_full_text_query(
value, language=transaction.language)
expression = database.search_full_text(column, value)
else:
expression = Literal(True)
for v in value.split():
expression &= ILike(column, '%' + v + '%')
if operator.startswith('not'):
expression = Not(expression)
else:
Operator = SQL_OPERATORS[operator]
column = self._rank_column(column, name, Model)
expression = Operator(column, self._domain_value(operator, value))
if isinstance(expression, In) and not expression.right:
expression = Literal(False)
elif isinstance(expression, NotIn) and not expression.right:
expression = Literal(True)
expression = self._domain_add_null(
column, operator, value, expression)
return expression
def convert_order(self, name, tables, Model):
method = getattr(Model, 'order_%s' % name, None)
if method:
return method(tables)
table, _ = tables[None]
column = self.sql_column(table)
column = self._domain_column('ilike', column)
column = self._rank_column(column, name, Model)
if column:
return [column]
return []