2525 get_prn ,
2626 get_view_name_for_model ,
2727 reverse ,
28- safe_in ,
2928)
3029from pulpcore .cache import Cache
3130from pulpcore .constants import ALL_KNOWN_CONTENT_CHECKSUMS , PROTECTED_REPO_VERSION_MESSAGE
@@ -909,6 +908,19 @@ def with_content(self, content):
909908 return self .filter (content_ids__overlap = content_pks )
910909
911910
911+ class RepositoryVersionManager (models .Manager ):
912+ """Manager that defers the content_ids array column by default.
913+
914+ The content_ids array can be very large and is expensive to transfer from
915+ PostgreSQL to Python. Most queries don't need it — callers that do
916+ (add_content, remove_content, set_content_ids, etc.) access it through
917+ the model instance which triggers a deferred-field load automatically.
918+ """
919+
920+ def get_queryset (self ):
921+ return RepositoryVersionQuerySet (self .model , using = self ._db ).defer ("content_ids" )
922+
923+
912924class RepositoryVersion (BaseModel ):
913925 """
914926 A version of a repository's content set.
@@ -937,7 +949,7 @@ class RepositoryVersion(BaseModel):
937949 base_version (models.ForeignKey): The repository version this was created from.
938950 """
939951
940- objects = RepositoryVersionQuerySet . as_manager ()
952+ objects = RepositoryVersionManager ()
941953
942954 repository = models .ForeignKey (Repository , on_delete = models .CASCADE )
943955 number = models .PositiveIntegerField (db_index = True )
@@ -975,6 +987,19 @@ def set_content_ids(self):
975987 else :
976988 self .content_ids = previous .content_ids
977989
990+ def _content_ids_subquery (self ):
991+ """Return a subquery that unnests content_ids server-side.
992+
993+ Keeps the array data inside PostgreSQL, avoiding the round-trip of
994+ loading a potentially huge list into Python and sending it back as
995+ query parameters.
996+ """
997+ return (
998+ RepositoryVersion .objects .filter (pk = self .pk )
999+ .annotate (cids = Func (F ("content_ids" ), function = "unnest" ))
1000+ .values_list ("cids" , flat = True )
1001+ )
1002+
9781003 def get_content (self , content_qs = None ):
9791004 """
9801005 Returns a set of content for a repository version
@@ -998,7 +1023,7 @@ def get_content(self, content_qs=None):
9981023 if content_qs is None :
9991024 content_qs = Content .objects
10001025
1001- return content_qs .filter (safe_in ( "pk" , self .content_ids ))
1026+ return content_qs .filter (pk__in = self ._content_ids_subquery ( ))
10021027
10031028 @property
10041029 def content (self ):
@@ -1112,8 +1137,8 @@ def added(self, base_version=None):
11121137 if not base_version :
11131138 return Content .objects .filter (version_memberships__version_added = self )
11141139
1115- return Content .objects .filter (safe_in ( "pk" , self .content_ids )).exclude (
1116- safe_in ( "pk" , base_version .content_ids )
1140+ return Content .objects .filter (pk__in = self ._content_ids_subquery ( )).exclude (
1141+ pk__in = base_version ._content_ids_subquery ( )
11171142 )
11181143
11191144 def removed (self , base_version = None ):
@@ -1127,8 +1152,8 @@ def removed(self, base_version=None):
11271152 if not base_version :
11281153 return Content .objects .filter (version_memberships__version_removed = self )
11291154
1130- return Content .objects .filter (safe_in ( "pk" , base_version .content_ids )).exclude (
1131- safe_in ( "pk" , self .content_ids )
1155+ return Content .objects .filter (pk__in = base_version ._content_ids_subquery ( )).exclude (
1156+ pk__in = self ._content_ids_subquery ( )
11321157 )
11331158
11341159 def contains (self , content ):
0 commit comments