Skip to content

Commit

Permalink
Fix PostgreSQL search index expressions
Browse files Browse the repository at this point in the history
Make sure to merge the indexes on the client side because the server
will not accept parameters in the CREATE INDEX statement.
  • Loading branch information
dvarrazzo committed Nov 22, 2021
1 parent a2bed86 commit f83ee2a
Showing 1 changed file with 21 additions and 5 deletions.
26 changes: 21 additions & 5 deletions django/contrib/postgres/search.py
Expand Up @@ -5,6 +5,20 @@
from django.db.models.functions import Cast, Coalesce


def merge_client_side(connection, query, params):
"""
Merge an sql expression and a sequence of parameters on the client side
"""
if connection.psycopg_version[0] > 2:
from psycopg import sql
else:
from psycopg2 import sql

query = sql.SQL(query.replace("{", "{{").replace("}", "}}").replace("%s", "{}"))
merged = query.format(*map(sql.Literal, params))
return merged.as_string(connection.cursor().cursor)


class SearchVectorExact(Lookup):
lookup_name = 'exact'

Expand Down Expand Up @@ -116,7 +130,11 @@ def as_sql(self, compiler, connection, function=None, template=None):
if clone.weight:
weight_sql, extra_params = compiler.compile(clone.weight)
sql = 'setweight({}, {})'.format(sql, weight_sql)
return sql, config_params + params + extra_params

# These parameters must be bound on the client side because we may
# want to create an index on this expression.
sql = merge_client_side(connection, sql, config_params + params + extra_params)
return sql, []


class CombinedSearchVector(SearchVectorCombinable, CombinedExpression):
Expand Down Expand Up @@ -266,10 +284,8 @@ def as_sql(self, compiler, connection, function=None, template=None):
if self.options:
# getquoted() returns a quoted bytestring of the adapted value.
options_params.append(', '.join(
'%s=%s' % (
option,
psycopg2.extensions.adapt(value).getquoted().decode(),
) for option, value in self.options.items()
merge_client_side(connection, "%s=%%s" % option, [value])
for option, value in self.options.items()
))
options_sql = ', %s'
sql, params = super().as_sql(
Expand Down

0 comments on commit f83ee2a

Please sign in to comment.