Skip to content

Commit

Permalink
Merge pull request #303 from thiagoferreiraw/master
Browse files Browse the repository at this point in the history
Change PostgresSearchBackend to optmize for UUID primary keys
  • Loading branch information
etianen authored Jan 14, 2023
2 parents 3674de1 + bbbbf3f commit b64a822
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 4 deletions.
19 changes: 15 additions & 4 deletions watson/backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from django.db.models.expressions import RawSQL, Value
from django.utils.encoding import force_str

from watson.models import SearchEntry, has_int_pk
from watson.models import SearchEntry, has_int_pk, has_uuid_pk


def regex_from_word(word):
Expand Down Expand Up @@ -282,22 +282,33 @@ def do_filter(self, engine_slug, queryset, search_text):
if has_int_pk(model):
ref_name = "object_id_int"
ref_name_typecast = ""
watson_id_typecast = ""
elif has_uuid_pk(model):
ref_name = "object_id"
# Moving the type cast happens on the watson_searchentry table.
# This ensures the primary key will be properly used.
ref_name_typecast = ""
watson_id_typecast = "::uuid"
else:
ref_name = "object_id"
# Cast to text to make join work with uuid columns
# Cast to text to make join work with other column types
ref_name_typecast = "::text"
watson_id_typecast = ""

return queryset.extra(
tables=("watson_searchentry",),
where=(
"watson_searchentry.engine_slug = %s",
"watson_searchentry.search_tsv @@ to_tsquery('{search_config}', %s)".format(
search_config=self.search_config
),
"watson_searchentry.{ref_name} = {table_name}.{pk_name}{ref_name_typecast}".format(
"watson_searchentry.{ref_name}{watson_id_typecast} = {table_name}.{pk_name}{ref_name_typecast}".format(

ref_name=ref_name,
table_name=connection.ops.quote_name(model._meta.db_table),
pk_name=connection.ops.quote_name(pk.db_column or pk.attname),
ref_name_typecast=ref_name_typecast
ref_name_typecast=ref_name_typecast,
watson_id_typecast=watson_id_typecast
),
"watson_searchentry.content_type_id = %s"
),
Expand Down
6 changes: 6 additions & 0 deletions watson/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ def has_int_pk(model):
)


def has_uuid_pk(model):
"""Tests whether the given model has an uuid primary key."""
pk = model._meta.pk
return isinstance(pk, models.UUIDField)


def get_str_pk(obj, connection):
return obj.pk.hex if isinstance(obj.pk, uuid.UUID) and connection.vendor != "postgresql" else force_str(obj.pk)

Expand Down

0 comments on commit b64a822

Please sign in to comment.