97 lines
3.4 KiB
Python
Executable File
97 lines
3.4 KiB
Python
Executable File
# 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 Expression, Literal, Null, Query
|
|
from sql.operators import ILike, In, Not, NotIn
|
|
|
|
from trytond.transaction import Transaction
|
|
|
|
from .char import Char
|
|
from .field import SQL_OPERATORS, Field, order_method
|
|
|
|
|
|
class Text(Char):
|
|
'''
|
|
Define a text field (``unicode``).
|
|
'''
|
|
_type = 'text'
|
|
_sql_type = 'TEXT'
|
|
forbidden_chars = ''
|
|
search_full_text = True
|
|
|
|
def __init__(self, *args, strip=False, **kwarg):
|
|
super().__init__(*args, strip=strip, **kwarg)
|
|
|
|
|
|
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
|
|
|
|
@order_method
|
|
def convert_order(self, name, tables, Model):
|
|
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 []
|