Fixed #29582 -- Fixed a crash when using SearchVector with non text-fields.
The PostgreSQL concat() function handles nulls and non-text values better than the || operator.
This commit is contained in:
parent
71a739f3d7
commit
1a28dc3887
|
@ -1,6 +1,5 @@
|
|||
from django.db.models import Field, FloatField
|
||||
from django.db.models.expressions import CombinedExpression, Func, Value
|
||||
from django.db.models.functions import Coalesce
|
||||
from django.db.models.lookups import Lookup
|
||||
|
||||
|
||||
|
@ -46,15 +45,13 @@ class SearchVectorCombinable:
|
|||
|
||||
class SearchVector(SearchVectorCombinable, Func):
|
||||
function = 'to_tsvector'
|
||||
arg_joiner = " || ' ' || "
|
||||
arg_joiner = ", ' ',"
|
||||
template = '%(function)s(concat(%(expressions)s))'
|
||||
output_field = SearchVectorField()
|
||||
config = None
|
||||
|
||||
def __init__(self, *expressions, **extra):
|
||||
super().__init__(*expressions, **extra)
|
||||
self.source_expressions = [
|
||||
Coalesce(expression, Value('')) for expression in self.source_expressions
|
||||
]
|
||||
self.config = self.extra.get('config', self.config)
|
||||
weight = self.extra.get('weight')
|
||||
if weight is not None and not hasattr(weight, 'resolve_expression'):
|
||||
|
@ -75,7 +72,7 @@ class SearchVector(SearchVectorCombinable, Func):
|
|||
if template is None:
|
||||
if self.config:
|
||||
config_sql, config_params = compiler.compile(self.config)
|
||||
template = "%(function)s({}::regconfig, %(expressions)s)".format(config_sql.replace('%', '%%'))
|
||||
template = "%(function)s({}::regconfig, concat(%(expressions)s))".format(config_sql.replace('%', '%%'))
|
||||
else:
|
||||
template = self.template
|
||||
sql, params = super().as_sql(compiler, connection, function=function, template=template)
|
||||
|
|
|
@ -155,6 +155,12 @@ class MultipleFieldsTest(GrailTestData, PostgreSQLTestCase):
|
|||
).filter(search='bedemir')
|
||||
self.assertEqual(set(searched), {self.bedemir0, self.bedemir1, self.crowd, self.witch, self.duck})
|
||||
|
||||
def test_search_with_non_text(self):
|
||||
searched = Line.objects.annotate(
|
||||
search=SearchVector('id'),
|
||||
).filter(search=str(self.crowd.id))
|
||||
self.assertSequenceEqual(searched, [self.crowd])
|
||||
|
||||
def test_config_query_explicit(self):
|
||||
searched = Line.objects.annotate(
|
||||
search=SearchVector('scene__setting', 'dialogue', config='french'),
|
||||
|
|
Loading…
Reference in New Issue