An unintended consequence is that if you pass it a value that contains a
percent sign, like {{{Value("10% OFF")}}}, the resulting {{{sql}}} will
have the {{{%}}} character inlined. Such values will result in a
{{{ProgrammingError}}} as soon as you attempt to combine the SearchVector
with any expression that relies on {{{params}}}.
Depending on whether you use psycopg2 or psycopg 3, the resulting error
will tell you that there are not enough params to format the query
template or that there is an unescaped {{{%}}} in the query.
--
Ticket URL: <https://code.djangoproject.com/ticket/34459>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* stage: Unreviewed => Accepted
Comment:
Tentatively accepting, I'm seeing errors but only when the args to
SearchVector are outside that which is documented to accept.
Felix & Simon will likely be able to clear things up.
So, to clarify, is this the behaviour you're seeing?
There's no issue if you filter by the search vector like so:
{{{
Foo.objects.annotate(search=SearchVector("text")).filter(search=Value("10%
off"))
}}}
It's when one of the arguments to SearchVector contain a percent that it
becomes an issue:
{{{
Foo.objects.annotate(search=SearchVector("text",
config="%")).filter(search=Value("10% off"))
...
django/db/models/query.py:373: in __repr__
data = list(self[: REPR_OUTPUT_SIZE + 1])
django/db/models/query.py:397: in __iter__
self._fetch_all()
django/db/models/query.py:1883: in _fetch_all
self._result_cache = list(self._iterable_class(self))
django/db/models/query.py:90: in __iter__
results = compiler.execute_sql(
django/db/models/sql/compiler.py:1560: in execute_sql
cursor.execute(sql, params)
django/db/backends/utils.py:67: in execute
return self._execute_with_wrappers(
django/db/backends/utils.py:80: in _execute_with_wrappers
return executor(sql, params, many, context)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <django.db.backends.utils.CursorWrapper object at 0x106e1bb20>
sql = 'SELECT "ticket_34459_foo"."id", "ticket_34459_foo"."text",
to_tsvector(\'%\'::regconfig,
COALESCE("ticket_34459_foo"....tsvector(\'%\'::regconfig,
COALESCE("ticket_34459_foo"."text", \'\')) @@
(plainto_tsquery(%s::regconfig, %s)) LIMIT 21'
params = ('%', '10% off')
ignored_wrapper_args = (False, {'connection': <DatabaseWrapper
vendor='postgresql' alias='default'>, 'cursor':
<django.db.backends.utils.CursorWrapper object at 0x106e1bb20>})
def _execute(self, sql, params, *ignored_wrapper_args):
self.db.validate_no_broken_transaction()
with self.db.wrap_database_errors:
if params is None:
# params default might be backend specific.
print(sql)
return self.cursor.execute(sql)
else:
> return self.cursor.execute(sql, params)
E IndexError: tuple index out of range
django/db/backends/utils.py:90: IndexError
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/34459#comment:1>