1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
|
from django.db.models import lookups
from django.db.models.fields import Field, related_lookups
from django.db.models.fields.related import ForeignObject
class InValuesLookupMixin:
"""Performs a `lhs IN VALUES ((a), (b), (c))` lookup.
This can be significantly faster then a normal `IN (a, b, c)`. The
latter sometimes causes the Postgres query planner do a sequential
scan.
"""
def as_sql(self, compiler, connection):
if not self.rhs_is_direct_value():
return super().as_sql(compiler, connection)
lhs, lhs_params = self.process_lhs(compiler, connection)
_, rhs_params = self.process_rhs(compiler, connection)
rhs = ",".join([f"(%s)" for _ in rhs_params]) # noqa: F541
return f"{lhs} IN (VALUES {rhs})", lhs_params + list(rhs_params)
@Field.register_lookup
class InValuesLookup(InValuesLookupMixin, lookups.In):
lookup_name = "invalues"
@ForeignObject.register_lookup
class InValuesRelatedLookup(InValuesLookupMixin, related_lookups.RelatedIn):
lookup_name = "invalues"
|