Skip to content

Commit d26aa99

Browse files
author
Andrew Cheng
committed
Mark content_ids as deferred and drop 65535 conditional for subquerying
1 parent d30e932 commit d26aa99

3 files changed

Lines changed: 17 additions & 9 deletions

File tree

pulpcore/app/models/repository.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -997,11 +997,7 @@ def get_content(self, content_qs=None):
997997
if content_qs is None:
998998
content_qs = Content.objects
999999

1000-
content_ids = self.content_ids
1001-
if len(content_ids) >= 65535:
1002-
# Workaround for PostgreSQL's limit on the number of parameters in a query
1003-
content_ids = self.content_ids_subquery()
1004-
return content_qs.filter(pk__in=content_ids)
1000+
return content_qs.filter(pk__in=self.content_ids_subquery())
10051001

10061002
def content_ids_subquery(self):
10071003
"""

pulpcore/app/viewsets/base.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ def get_resource_model(uri):
157157
return match.func.cls.queryset.model
158158

159159
@staticmethod
160-
def get_resource(uri, model=None):
160+
def get_resource(uri, model=None, deferred_fields=None):
161161
"""
162162
Resolve a resource URI/PRN to an instance of the resource.
163163
@@ -168,6 +168,9 @@ def get_resource(uri, model=None):
168168
uri (str): A resource URI/PRN.
169169
model (django.models.Model): A model class. If not provided, the method automatically
170170
determines the used model from the resource URI/PRN.
171+
deferred_fields (iterable): Optional field names to defer when loading the resource, so
172+
large columns are not fetched from the database. Field names that do not exist on
173+
the resolved model are ignored.
171174
172175
Returns:
173176
django.models.Model: The resource fetched from the DB.
@@ -207,7 +210,13 @@ def get_resource(uri, model=None):
207210
kwargs[key] = value
208211

209212
try:
210-
return model.objects.get(**kwargs)
213+
manager = model.objects
214+
if deferred_fields:
215+
model_fields = {field.name for field in model._meta.concrete_fields}
216+
to_defer = [name for name in deferred_fields if name in model_fields]
217+
if to_defer:
218+
manager = manager.defer(*to_defer)
219+
return manager.get(**kwargs)
211220
except model.MultipleObjectsReturned:
212221
raise DRFValidationError(
213222
detail=_("URI {u} matches more than one {m}.").format(

pulpcore/app/viewsets/custom_filters.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,12 @@ def get_repository_version(value):
145145
detail=_("No value supplied for repository version filter")
146146
)
147147

148-
object = NamedModelViewSet.get_resource(value)
148+
# content_ids is only consumed as a database-side subquery (see
149+
# RepositoryVersion.content_ids_subquery), so defer the potentially huge array column here
150+
# to keep it from being loaded into Python when resolving the version.
151+
object = NamedModelViewSet.get_resource(value, deferred_fields=("content_ids",))
149152
if isinstance(object, Repository):
150-
object = object.latest_version()
153+
object = object.versions.complete().defer("content_ids").last()
151154
if not isinstance(object, RepositoryVersion):
152155
raise serializers.ValidationError(
153156
detail=_("URI {u} not found for {m}.").format(u=value, m="repositoryversion")

0 commit comments

Comments
 (0)