From a50112c53465161c139de338655858a420125daa Mon Sep 17 00:00:00 2001 From: Adam Goldsmith Date: Fri, 1 Dec 2023 13:05:27 -0500 Subject: [PATCH] paperwork: Use window functions for CertificationVersion is_current/is_latest This should be a lot more efficient, and is much cleaner code too --- paperwork/models.py | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/paperwork/models.py b/paperwork/models.py index 10a186b..7d6c3ba 100644 --- a/paperwork/models.py +++ b/paperwork/models.py @@ -4,7 +4,8 @@ from typing import TypedDict, TYPE_CHECKING, Optional from semver import VersionInfo from django.db import models -from django.db.models import OuterRef, Q, ExpressionWrapper, Subquery +from django.db.models import Q, Window +from django.db.models.functions import FirstValue from django.conf import settings from django.core.validators import RegexValidator from django_stubs_ext import WithAnnotations @@ -139,18 +140,23 @@ class CertificationVersionAnnotations(TypedDict): class CertificationVersionManager(models.Manager["CertificationVersion"]): def get_queryset(self) -> models.QuerySet["CertificationVersion"]: - qs = super().get_queryset() - latest = qs.filter(definition__pk=OuterRef("definition__pk")).reverse() - return qs.annotate( - is_latest=ExpressionWrapper( - Q(pk=Subquery(latest.values("pk")[:1])), - output_field=models.BooleanField(), - ), - # TODO: should do a more correct comparison than just major version - is_current=ExpressionWrapper( - Q(major=Subquery(latest.values("major")[:1])), - output_field=models.BooleanField(), - ), + window = { + "partition_by": "definition", + "order_by": [ + "-major", + "-minor", + "-patch", + "-prerelease", + ], + } + return ( + super() + .get_queryset() + .annotate( + is_latest=Q(pk=Window(FirstValue("pk"), **window)), + # TODO: should do a more correct comparison than just major version + is_current=Q(major=Window(FirstValue("major"), **window)), + ) )