← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/launchpad:stormify-xpph-queries into launchpad:master

 

Colin Watson has proposed merging ~cjwatson/launchpad:stormify-xpph-queries into launchpad:master.

Commit message:
Convert remaining publishing history queries to Storm

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/394764
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:stormify-xpph-queries into launchpad:master.
diff --git a/lib/lp/archiveuploader/tests/test_ppauploadprocessor.py b/lib/lp/archiveuploader/tests/test_ppauploadprocessor.py
index 2be7342..899a85e 100644
--- a/lib/lp/archiveuploader/tests/test_ppauploadprocessor.py
+++ b/lib/lp/archiveuploader/tests/test_ppauploadprocessor.py
@@ -28,6 +28,7 @@ from lp.registry.interfaces.person import IPersonSet
 from lp.registry.interfaces.pocket import PackagePublishingPocket
 from lp.services.config import config
 from lp.services.database.constants import UTC_NOW
+from lp.services.database.interfaces import IStore
 from lp.services.librarian.interfaces import ILibraryFileAliasSet
 from lp.soyuz.enums import (
     PackagePublishingStatus,
@@ -329,7 +330,8 @@ class TestPPAUploadProcessor(TestPPAUploadProcessorBase):
 
         for binary_package in build.binarypackages:
             self.assertEqual(binary_package.component.name, "universe")
-            [binary_pub] = BinaryPackagePublishingHistory.selectBy(
+            [binary_pub] = IStore(BinaryPackagePublishingHistory).find(
+                BinaryPackagePublishingHistory,
                 binarypackagerelease=binary_package,
                 archive=self.name16.archive)
             self.assertEqual(binary_pub.component.name, "main")
diff --git a/lib/lp/archiveuploader/tests/test_uploadprocessor.py b/lib/lp/archiveuploader/tests/test_uploadprocessor.py
index 6fb09fb..91ec622 100644
--- a/lib/lp/archiveuploader/tests/test_uploadprocessor.py
+++ b/lib/lp/archiveuploader/tests/test_uploadprocessor.py
@@ -63,6 +63,7 @@ from lp.registry.interfaces.sourcepackagename import ISourcePackageNameSet
 from lp.registry.model.sourcepackagename import SourcePackageName
 from lp.services.config import config
 from lp.services.database.constants import UTC_NOW
+from lp.services.database.interfaces import IStore
 from lp.services.librarian.interfaces import ILibraryFileAliasSet
 from lp.services.log.logger import (
     BufferLogger,
@@ -1022,8 +1023,9 @@ class TestUploadProcessor(TestUploadProcessorBase):
         self.publishPackage("foocomm", "1.0-1", archive=partner_archive)
 
         # Check the publishing record's archive and component.
-        foocomm_spph = SourcePackagePublishingHistory.selectOneBy(
-            sourcepackagerelease=foocomm_spr)
+        foocomm_spph = IStore(SourcePackagePublishingHistory).find(
+            SourcePackagePublishingHistory,
+            sourcepackagerelease=foocomm_spr).one()
         self.assertEqual(foocomm_spph.archive.description,
             'Partner archive')
         self.assertEqual(foocomm_spph.component.name,
@@ -1066,8 +1068,9 @@ class TestUploadProcessor(TestUploadProcessorBase):
         self.publishPackage("foocomm", "1.0-1", source=False)
 
         # Check the publishing record's archive and component.
-        foocomm_bpph = BinaryPackagePublishingHistory.selectOneBy(
-            binarypackagerelease=foocomm_bpr)
+        foocomm_bpph = IStore(BinaryPackagePublishingHistory).find(
+            BinaryPackagePublishingHistory,
+            binarypackagerelease=foocomm_bpr).one()
         self.assertEqual(foocomm_bpph.archive.description,
             'Partner archive')
         self.assertEqual(foocomm_bpph.component.name,
diff --git a/lib/lp/registry/doc/sourcepackage.txt b/lib/lp/registry/doc/sourcepackage.txt
index e494a68..c8a6508 100644
--- a/lib/lp/registry/doc/sourcepackage.txt
+++ b/lib/lp/registry/doc/sourcepackage.txt
@@ -127,13 +127,14 @@ upload, even though it gets changed in the publishing record.
     PENDING main
     PUBLISHED main
 
+    >>> from lp.services.database.interfaces import IStore
     >>> from lp.services.database.sqlbase import flush_database_caches
     >>> from lp.soyuz.model.component import Component
     >>> from lp.soyuz.model.publishing import (
     ...     SourcePackagePublishingHistory)
 
-    >>> latest_publishing = SourcePackagePublishingHistory.get(
-    ...     publishing_history[-1].id)
+    >>> latest_publishing = IStore(SourcePackagePublishingHistory).get(
+    ...     SourcePackagePublishingHistory, publishing_history.last().id)
     >>> universe = Component.byName('universe')
     >>> latest_publishing.component = universe
     >>> flush_database_caches()
diff --git a/lib/lp/registry/model/distributionmirror.py b/lib/lp/registry/model/distributionmirror.py
index 323fb26..11f2b13 100644
--- a/lib/lp/registry/model/distributionmirror.py
+++ b/lib/lp/registry/model/distributionmirror.py
@@ -835,32 +835,35 @@ class MirrorDistroArchSeries(SQLBase, _MirrorSeriesMixIn):
                    binarypackagerelease's binarypackagefile.filetype is
                    BinaryPackageFileType.DEB.
         """
-        query = """
-            BinaryPackagePublishingHistory.pocket = %s
-            AND BinaryPackagePublishingHistory.component = %s
-            AND BinaryPackagePublishingHistory.distroarchseries = %s
-            AND BinaryPackagePublishingHistory.archive = %s
-            AND BinaryPackagePublishingHistory.status = %s
-            """ % sqlvalues(self.pocket, self.component,
-                            self.distro_arch_series,
-                            self.distro_arch_series.main_archive,
-                            PackagePublishingStatus.PUBLISHED)
+        clauses = [
+            BinaryPackagePublishingHistory.pocket == self.pocket,
+            BinaryPackagePublishingHistory.component == self.component,
+            BinaryPackagePublishingHistory.distroarchseries ==
+                self.distro_arch_series,
+            BinaryPackagePublishingHistory.archive ==
+                self.distro_arch_series.main_archive,
+            BinaryPackagePublishingHistory.status ==
+                PackagePublishingStatus.PUBLISHED,
+            ]
 
         if deb_only:
-            query += """
-                AND BinaryPackagePublishingHistory.binarypackagerelease =
-                    BinaryPackageFile.binarypackagerelease
-                AND BinaryPackageFile.filetype = %s
-                """ % sqlvalues(BinaryPackageFileType.DEB)
+            clauses.extend([
+                BinaryPackagePublishingHistory.binarypackagerelease ==
+                    BinaryPackageFile.binarypackagerelease,
+                BinaryPackageFile.filetype == BinaryPackageFileType.DEB,
+                ])
 
         if time_interval is not None:
             start, end = time_interval
             assert end > start, '%s is not more recent than %s' % (end, start)
-            query = (query + " AND datepublished >= %s AND datepublished < %s"
-                     % sqlvalues(start, end))
-        return BinaryPackagePublishingHistory.selectFirst(
-            query, clauseTables=['BinaryPackageFile'],
-            orderBy='-datepublished')
+            clauses.extend([
+                BinaryPackagePublishingHistory.datepublished >= start,
+                BinaryPackagePublishingHistory.datepublished < end,
+                ])
+        rows = IStore(BinaryPackagePublishingHistory).find(
+            BinaryPackagePublishingHistory,
+            *clauses).order_by(BinaryPackagePublishingHistory.datepublished)
+        return rows.last()
 
     def _getPackageReleaseURLFromPublishingRecord(self, publishing_record):
         """Return the URL on this mirror from where the BinaryPackageRelease.
@@ -898,24 +901,27 @@ class MirrorDistroSeriesSource(SQLBase, _MirrorSeriesMixIn):
         notNull=True, schema=PackagePublishingPocket)
 
     def getLatestPublishingEntry(self, time_interval):
-        query = """
-            SourcePackagePublishingHistory.pocket = %s
-            AND SourcePackagePublishingHistory.component = %s
-            AND SourcePackagePublishingHistory.distroseries = %s
-            AND SourcePackagePublishingHistory.archive = %s
-            AND SourcePackagePublishingHistory.status = %s
-            """ % sqlvalues(self.pocket, self.component,
-                            self.distroseries,
-                            self.distroseries.main_archive,
-                            PackagePublishingStatus.PUBLISHED)
+        clauses = [
+            SourcePackagePublishingHistory.pocket == self.pocket,
+            SourcePackagePublishingHistory.component == self.component,
+            SourcePackagePublishingHistory.distroseries == self.distroseries,
+            SourcePackagePublishingHistory.archive ==
+                self.distroseries.main_archive,
+            SourcePackagePublishingHistory.status ==
+                PackagePublishingStatus.PUBLISHED,
+            ]
 
         if time_interval is not None:
             start, end = time_interval
             assert end > start
-            query = (query + " AND datepublished >= %s AND datepublished < %s"
-                     % sqlvalues(start, end))
-        return SourcePackagePublishingHistory.selectFirst(
-            query, orderBy='-datepublished')
+            clauses.extend([
+                SourcePackagePublishingHistory.datepublished >= start,
+                SourcePackagePublishingHistory.datepublished < end,
+                ])
+        rows = IStore(SourcePackagePublishingHistory).find(
+            SourcePackagePublishingHistory,
+            *clauses).order_by(SourcePackagePublishingHistory.datepublished)
+        return rows.last()
 
     def _getPackageReleaseURLFromPublishingRecord(self, publishing_record):
         """return the URL on this mirror from where the SourcePackageRelease.
diff --git a/lib/lp/registry/model/distributionsourcepackage.py b/lib/lp/registry/model/distributionsourcepackage.py
index da4a021..3224251 100644
--- a/lib/lp/registry/model/distributionsourcepackage.py
+++ b/lib/lp/registry/model/distributionsourcepackage.py
@@ -18,15 +18,18 @@ from operator import (
 from threading import local
 
 from breezy.lru_cache import LRUCache
-from sqlobject.sqlbuilder import SQLConstant
+import six
 from storm.expr import (
     And,
+    Cast,
     Desc,
     )
 from storm.locals import (
     Bool,
     Int,
+    Not,
     Reference,
+    SQL,
     Store,
     Storm,
     Unicode,
@@ -59,7 +62,6 @@ from lp.registry.model.sourcepackage import (
 from lp.services.database.bulk import load
 from lp.services.database.decoratedresultset import DecoratedResultSet
 from lp.services.database.interfaces import IStore
-from lp.services.database.sqlbase import sqlvalues
 from lp.services.propertycache import cachedproperty
 from lp.soyuz.enums import (
     ArchivePurpose,
@@ -228,53 +230,48 @@ class DistributionSourcePackage(BugTargetBase,
         # and pocket enum values, which is arguably evil but much faster
         # than CASE sorting; at any rate this can be fixed when
         # https://bugs.launchpad.net/soyuz/+bug/236922 is.
-        spph = SourcePackagePublishingHistory.selectFirst("""
-            SourcePackagePublishingHistory.distroseries = DistroSeries.id AND
-            DistroSeries.distribution = %s AND
-            SourcePackagePublishingHistory.sourcepackagename = %s AND
-            SourcePackagePublishingHistory.archive IN %s AND
-            pocket NOT IN (%s, %s) AND
-            status in (%s, %s)""" %
-                sqlvalues(self.distribution,
-                          self.sourcepackagename,
-                          self.distribution.all_distro_archive_ids,
-                          PackagePublishingPocket.PROPOSED,
-                          PackagePublishingPocket.BACKPORTS,
-                          PackagePublishingStatus.PUBLISHED,
-                          PackagePublishingStatus.OBSOLETE),
-            clauseTables=["SourcePackagePublishingHistory",
-                          "DistroSeries"],
-            orderBy=["status",
-                     SQLConstant(
-                        "to_number(DistroSeries.version, '99.99') DESC"),
-                     "-pocket"])
+        spph = IStore(SourcePackagePublishingHistory).find(
+            SourcePackagePublishingHistory,
+            SourcePackagePublishingHistory.distroseries == DistroSeries.id,
+            DistroSeries.distribution == self.distribution,
+            SourcePackagePublishingHistory.sourcepackagename ==
+                self.sourcepackagename,
+            SourcePackagePublishingHistory.archiveID.is_in(
+                self.distribution.all_distro_archive_ids),
+            Not(SourcePackagePublishingHistory.pocket.is_in({
+                PackagePublishingPocket.PROPOSED,
+                PackagePublishingPocket.BACKPORTS,
+                })),
+            SourcePackagePublishingHistory.status.is_in({
+                PackagePublishingStatus.PUBLISHED,
+                PackagePublishingStatus.OBSOLETE,
+                }),
+            ).order_by(
+                SourcePackagePublishingHistory.status,
+                SQL("to_number(DistroSeries.version, '99.99') DESC"),
+                Desc(SourcePackagePublishingHistory.pocket),
+                ).first()
         return spph
 
     def getVersion(self, version):
         """See `IDistributionSourcePackage`."""
-        spph = SourcePackagePublishingHistory.select("""
-            SourcePackagePublishingHistory.distroseries =
-                DistroSeries.id AND
-            DistroSeries.distribution = %s AND
-            SourcePackagePublishingHistory.archive IN %s AND
-            SourcePackagePublishingHistory.sourcepackagerelease =
-                SourcePackageRelease.id AND
-            SourcePackagePublishingHistory.sourcepackagename = %s AND
-            SourcePackageRelease.sourcepackagename = %s AND
-            SourcePackageRelease.version::text = %s
-            """ % sqlvalues(self.distribution,
-                            self.distribution.all_distro_archive_ids,
-                            self.sourcepackagename,
-                            self.sourcepackagename,
-                            version),
-            orderBy='-datecreated',
-            prejoinClauseTables=['SourcePackageRelease'],
-            clauseTables=['DistroSeries', 'SourcePackageRelease'])
-        if spph.is_empty():
+        spr = IStore(SourcePackagePublishingHistory).find(
+            SourcePackageRelease,
+            SourcePackagePublishingHistory.distroseries == DistroSeries.id,
+            DistroSeries.distribution == self.distribution,
+            SourcePackagePublishingHistory.archiveID.is_in(
+                self.distribution.all_distro_archive_ids),
+            SourcePackagePublishingHistory.sourcepackagerelease ==
+                SourcePackageRelease.id,
+            SourcePackagePublishingHistory.sourcepackagename == self.sourcepackagename,
+            SourcePackageRelease.sourcepackagename == self.sourcepackagename,
+            Cast(SourcePackageRelease.version, "text") ==
+                six.ensure_text(version),
+            ).order_by(SourcePackagePublishingHistory.datecreated).last()
+        if spr is None:
             return None
         return DistributionSourcePackageRelease(
-            distribution=self.distribution,
-            sourcepackagerelease=spph[0].sourcepackagerelease)
+            distribution=self.distribution, sourcepackagerelease=spr)
 
     # XXX kiko 2006-08-16: Bad method name, no need to be a property.
     @property
diff --git a/lib/lp/registry/model/sourcepackage.py b/lib/lp/registry/model/sourcepackage.py
index 61b66e4..acc0bf9 100644
--- a/lib/lp/registry/model/sourcepackage.py
+++ b/lib/lp/registry/model/sourcepackage.py
@@ -10,7 +10,10 @@ __all__ = [
     'SourcePackageQuestionTargetMixin',
     ]
 
-from operator import attrgetter
+from operator import (
+    attrgetter,
+    itemgetter,
+    )
 
 from storm.locals import (
     And,
@@ -58,6 +61,7 @@ from lp.registry.model.packaging import (
     PackagingUtil,
     )
 from lp.registry.model.suitesourcepackage import SuiteSourcePackage
+from lp.services.database.decoratedresultset import DecoratedResultSet
 from lp.services.database.interfaces import IStore
 from lp.services.database.sqlbase import (
     flush_database_updates,
@@ -224,31 +228,29 @@ class SourcePackage(BugTargetBase, HasCodeImportsMixin,
         not duplicated. include_status must be a sequence.
         """
         clauses = []
-        clauses.append(
-                """SourcePackagePublishingHistory.sourcepackagerelease =
-                   SourcePackageRelease.id AND
-                   SourcePackagePublishingHistory.sourcepackagename = %s AND
-                   SourcePackagePublishingHistory.distroseries = %s AND
-                   SourcePackagePublishingHistory.archive IN %s
-                """ % sqlvalues(
-                        self.sourcepackagename,
-                        self.distroseries,
-                        self.distribution.all_distro_archive_ids))
+        clauses.extend([
+            SourcePackagePublishingHistory.sourcepackagerelease ==
+                SourcePackageRelease.id,
+            SourcePackagePublishingHistory.sourcepackagename ==
+                self.sourcepackagename,
+            SourcePackagePublishingHistory.distroseries == self.distroseries,
+            SourcePackagePublishingHistory.archiveID.is_in(
+                self.distribution.all_distro_archive_ids),
+            ])
 
         if include_status:
             if not isinstance(include_status, list):
                 include_status = list(include_status)
-            clauses.append("SourcePackagePublishingHistory.status IN %s"
-                       % sqlvalues(include_status))
-
-        query = " AND ".join(clauses)
+            clauses.append(
+                SourcePackagePublishingHistory.status.is_in(include_status))
 
         if not order_by:
-            order_by = '-datepublished'
+            order_by = [Desc(SourcePackagePublishingHistory.datepublished)]
 
-        return SourcePackagePublishingHistory.select(
-            query, orderBy=order_by, clauseTables=['SourcePackageRelease'],
-            prejoinClauseTables=['SourcePackageRelease'])
+        rows = IStore(SourcePackagePublishingHistory).find(
+            (SourcePackagePublishingHistory, SourcePackageRelease),
+            *clauses).order_by(*order_by)
+        return DecoratedResultSet(rows, itemgetter(0))
 
     def _getFirstPublishingHistory(self, include_status=None, order_by=None):
         """As _getPublishingHistory, but just returns the first item."""
@@ -330,8 +332,8 @@ class SourcePackage(BugTargetBase, HasCodeImportsMixin,
     def releases(self):
         """See `ISourcePackage`."""
         packages = self._getPublishingHistory(
-            order_by=["SourcePackageRelease.version",
-                      "SourcePackagePublishingHistory.datepublished"])
+            order_by=[SourcePackageRelease.version,
+                      SourcePackagePublishingHistory.datepublished])
 
         return [DistributionSourcePackageRelease(
                 distribution=self.distribution,
diff --git a/lib/lp/soyuz/doc/distroarchseriesbinarypackage.txt b/lib/lp/soyuz/doc/distroarchseriesbinarypackage.txt
index c759bbf..54d8cad 100644
--- a/lib/lp/soyuz/doc/distroarchseriesbinarypackage.txt
+++ b/lib/lp/soyuz/doc/distroarchseriesbinarypackage.txt
@@ -236,6 +236,7 @@ Then, supersede all pmount publications in warty for pmount (this sets
 us up to demonstrate bug 208233).
 
     >>> switch_dbuser('archivepublisher')
+    >>> from lp.services.database.interfaces import IStore
     >>> from lp.soyuz.model.binarypackagename import BinaryPackageName
     >>> from lp.soyuz.model.distroarchseries import DistroArchSeries
     >>> from lp.soyuz.model.distroarchseriesbinarypackage import (
@@ -245,10 +246,11 @@ us up to demonstrate bug 208233).
     >>> pmount_name = BinaryPackageName.selectOneBy(name="pmount")
     >>> pmount_warty_i386 = DistroArchSeriesBinaryPackage(warty_i386,
     ...                                                      pmount_name)
-    >>> pubs = BinaryPackagePublishingHistory.selectBy(
-    ...          archive=1,
-    ...          distroarchseries=warty_i386,
-    ...          status=PackagePublishingStatus.PUBLISHED)
+    >>> pubs = IStore(BinaryPackagePublishingHistory).find(
+    ...     BinaryPackagePublishingHistory,
+    ...     archive=1,
+    ...     distroarchseries=warty_i386,
+    ...     status=PackagePublishingStatus.PUBLISHED)
     >>> for p in pubs:
     ...      if p.binarypackagerelease.binarypackagename == pmount_name:
     ...          s = p.supersede()
diff --git a/lib/lp/soyuz/doc/distroseriesqueue.txt b/lib/lp/soyuz/doc/distroseriesqueue.txt
index bb859f5..40bb389 100644
--- a/lib/lp/soyuz/doc/distroseriesqueue.txt
+++ b/lib/lp/soyuz/doc/distroseriesqueue.txt
@@ -105,10 +105,12 @@ XXX cprov 20051209: need to build a broken upload to test it properly
 
 Confirm we can now find ed published in hoary.
 
+    >>> from lp.services.database.interfaces import IStore
     >>> from lp.soyuz.enums import PackagePublishingStatus
     >>> from lp.soyuz.model.publishing import SourcePackagePublishingHistory
-    >>> for release in SourcePackagePublishingHistory.selectBy(
-    ...     distroseries=hoary, status=PackagePublishingStatus.PENDING):
+    >>> for release in IStore(SourcePackagePublishingHistory).find(
+    ...         SourcePackagePublishingHistory,
+    ...         distroseries=hoary, status=PackagePublishingStatus.PENDING):
     ...     if release.sourcepackagerelease.sourcepackagename.name == "ed":
     ...         print(release.sourcepackagerelease.version)
     0.2-20
diff --git a/lib/lp/soyuz/doc/gina.txt b/lib/lp/soyuz/doc/gina.txt
index 1f773df..7c60af4 100644
--- a/lib/lp/soyuz/doc/gina.txt
+++ b/lib/lp/soyuz/doc/gina.txt
@@ -7,6 +7,7 @@ quiet mode over it.
 
 Get the current counts of stuff in the database:
 
+    >>> from lp.services.database.interfaces import IStore
     >>> from lp.services.identity.model.emailaddress import EmailAddress
     >>> from lp.soyuz.interfaces.publishing import active_publishing_status
     >>> from lp.soyuz.model.publishing import (
@@ -454,8 +455,9 @@ We check that the binary package publishing override facility works:
     >>> n = BinaryPackageName.selectOneBy(name="libdb1-compat")
     >>> db1 = BinaryPackageRelease.selectOneBy(binarypackagenameID=n.id,
     ...         version="2.1.3-7")
-    >>> for pub in BinaryPackagePublishingHistory.selectBy(
-    ...     binarypackagereleaseID=db1.id, orderBy='distroarchseries'):
+    >>> for pub in IStore(BinaryPackagePublishingHistory).find(
+    ...         BinaryPackagePublishingHistory,
+    ...         binarypackagerelease=db1).order_by('distroarchseries'):
     ...     print("%s %s %s" % (
     ...         pub.distroarchseries.distroseries.name, pub.priority,
     ...         pub.archive.purpose.name))
diff --git a/lib/lp/soyuz/doc/publishing.txt b/lib/lp/soyuz/doc/publishing.txt
index 1fd1eb5..a2c3b3f 100644
--- a/lib/lp/soyuz/doc/publishing.txt
+++ b/lib/lp/soyuz/doc/publishing.txt
@@ -4,6 +4,7 @@ SourcePackagePublishingHistory
 
 This class provides public access to publishing records via a SQL view.
 
+    >>> from lp.services.database.interfaces import IStore
     >>> from lp.soyuz.model.publishing import (
     ...     BinaryPackagePublishingHistory,
     ...     SourcePackagePublishingHistory,
@@ -12,7 +13,8 @@ This class provides public access to publishing records via a SQL view.
 Select a publishing record from the sampledata (pmount is a
 interesting one):
 
-    >>> spph = SourcePackagePublishingHistory.get(8)
+    >>> spph = IStore(SourcePackagePublishingHistory).get(
+    ...     SourcePackagePublishingHistory, 8)
     >>> spph.sourcepackagerelease.name, spph.distroseries.name
     (u'pmount', u'hoary')
 
@@ -312,7 +314,8 @@ Retrieve any SourcePackagePublishingHistory entry.
     ...     ISourcePackageReleaseFile)
     >>> from lp.soyuz.interfaces.publishing import (
     ...     IBinaryPackagePublishingHistory)
-    >>> spph = SourcePackagePublishingHistory.get(10)
+    >>> spph = IStore(SourcePackagePublishingHistory).get(
+    ...     SourcePackagePublishingHistory, 10)
 
     >>> print(spph.displayname)
     alsa-utils 1.0.8-1ubuntu1 in warty
@@ -483,10 +486,13 @@ archive index.
 Let's retrieve the 'insecure' corresponding publishing records since
 only they provide the API we are interested in.
 
-    >>> copied_source = SourcePackagePublishingHistory.get(copied_source.id)
+    >>> copied_source = IStore(SourcePackagePublishingHistory).get(
+    ...     SourcePackagePublishingHistory, copied_source.id)
 
-    >>> copied_binaries = [BinaryPackagePublishingHistory.get(bin.id)
-    ...                    for bin in copied_binaries]
+    >>> copied_binaries = [
+    ...     IStore(BinaryPackagePublishingHistory).get(
+    ...         BinaryPackagePublishingHistory, bin.id)
+    ...     for bin in copied_binaries]
 
 When we call createMissingBuilds method on the copied sources it won't
 create any builds since the binaries were copied over too.
@@ -740,8 +746,8 @@ Perform the source-only copy.
     >>> ppa_copied_source = ppa_source.copyTo(
     ...     hoary_test, PackagePublishingPocket.RELEASE, cprov.archive)
 
-    >>> ppa_copied_source = SourcePackagePublishingHistory.get(
-    ...     ppa_copied_source.id)
+    >>> ppa_copied_source = IStore(SourcePackagePublishingHistory).get(
+    ...     SourcePackagePublishingHistory, ppa_copied_source.id)
 
 createMissingBuilds will not create any builds because this is an
 intra-archive copy:
@@ -810,7 +816,8 @@ Let's perform the copy of the source and its i386 binary.
 
 The source and binary are present in hoary-test:
 
-    >>> copied_source = SourcePackagePublishingHistory.get(copied_source.id)
+    >>> copied_source = IStore(SourcePackagePublishingHistory).get(
+    ...     SourcePackagePublishingHistory, copied_source.id)
     >>> print(copied_source.displayname)
     mno 999 in hoary-test
 
@@ -879,7 +886,8 @@ BinaryPackageFile and IBinaryPackagePublishingHistory
     >>> from lp.soyuz.interfaces.files import (
     ...     IBinaryPackageFile)
 
-    >>> bpph = BinaryPackagePublishingHistory.get(15)
+    >>> bpph = IStore(BinaryPackagePublishingHistory).get(
+    ...     BinaryPackagePublishingHistory, 15)
     >>> print(bpph.displayname)
     mozilla-firefox 0.9 in woody i386
 
diff --git a/lib/lp/soyuz/model/archive.py b/lib/lp/soyuz/model/archive.py
index 88e949e..50774b5 100644
--- a/lib/lp/soyuz/model/archive.py
+++ b/lib/lp/soyuz/model/archive.py
@@ -2846,19 +2846,20 @@ class ArchiveSet:
 
     def getLatestPPASourcePublicationsForDistribution(self, distribution):
         """See `IArchiveSet`."""
-        query = """
-            SourcePackagePublishingHistory.archive = Archive.id AND
-            SourcePackagePublishingHistory.distroseries =
-                DistroSeries.id AND
-            Archive.private = FALSE AND
-            Archive.enabled = TRUE AND
-            DistroSeries.distribution = %s AND
-            Archive.purpose = %s
-        """ % sqlvalues(distribution, ArchivePurpose.PPA)
+        # Circular import.
+        from lp.registry.model.distroseries import DistroSeries
 
-        return SourcePackagePublishingHistory.select(
-            query, limit=5, clauseTables=['Archive', 'DistroSeries'],
-            orderBy=['-datecreated', '-id'])
+        return IStore(SourcePackagePublishingHistory).find(
+            SourcePackagePublishingHistory,
+            SourcePackagePublishingHistory.archive == Archive.id,
+            SourcePackagePublishingHistory.distroseries == DistroSeries.id,
+            Archive._private == False,
+            Archive._enabled == True,
+            DistroSeries.distribution == distribution,
+            Archive.purpose == ArchivePurpose.PPA,
+            ).order_by(
+                Desc(SourcePackagePublishingHistory.datecreated),
+                Desc(SourcePackagePublishingHistory.id))[:5]
 
     def getMostActivePPAsForDistribution(self, distribution):
         """See `IArchiveSet`."""
diff --git a/lib/lp/soyuz/model/distroarchseries.py b/lib/lp/soyuz/model/distroarchseries.py
index ea8d5ee..cc70bc8 100644
--- a/lib/lp/soyuz/model/distroarchseries.py
+++ b/lib/lp/soyuz/model/distroarchseries.py
@@ -36,10 +36,7 @@ from lp.services.database.constants import DEFAULT
 from lp.services.database.decoratedresultset import DecoratedResultSet
 from lp.services.database.enumcol import EnumCol
 from lp.services.database.interfaces import IStore
-from lp.services.database.sqlbase import (
-    SQLBase,
-    sqlvalues,
-    )
+from lp.services.database.sqlbase import SQLBase
 from lp.services.database.stormexpr import (
     fti_search,
     rank_by_fti,
@@ -114,19 +111,16 @@ class DistroArchSeries(SQLBase):
         """See `IDistroArchSeries`."""
         from lp.soyuz.model.publishing import BinaryPackagePublishingHistory
 
-        query = """
-            BinaryPackagePublishingHistory.distroarchseries = %s AND
-            BinaryPackagePublishingHistory.archive IN %s AND
-            BinaryPackagePublishingHistory.status = %s AND
-            BinaryPackagePublishingHistory.pocket = %s
-            """ % sqlvalues(
-                    self,
-                    self.distroseries.distribution.all_distro_archive_ids,
-                    PackagePublishingStatus.PUBLISHED,
-                    PackagePublishingPocket.RELEASE
-                 )
-        self.package_count = BinaryPackagePublishingHistory.select(
-            query).count()
+        self.package_count = IStore(BinaryPackagePublishingHistory).find(
+            BinaryPackagePublishingHistory,
+            BinaryPackagePublishingHistory.distroarchseries == self,
+            BinaryPackagePublishingHistory.archiveID.is_in(
+                self.distroseries.distribution.all_distro_archive_ids),
+            BinaryPackagePublishingHistory.status ==
+                PackagePublishingStatus.PUBLISHED,
+            BinaryPackagePublishingHistory.pocket ==
+                PackagePublishingPocket.RELEASE,
+            ).count()
 
     @property
     def isNominatedArchIndep(self):
diff --git a/lib/lp/soyuz/model/distroarchseriesbinarypackagerelease.py b/lib/lp/soyuz/model/distroarchseriesbinarypackagerelease.py
index ace0b80..360af52 100644
--- a/lib/lp/soyuz/model/distroarchseriesbinarypackagerelease.py
+++ b/lib/lp/soyuz/model/distroarchseriesbinarypackagerelease.py
@@ -10,9 +10,10 @@ __all__ = [
     'DistroArchSeriesBinaryPackageRelease',
     ]
 
+from storm.locals import Desc
 from zope.interface import implementer
 
-from lp.services.database.sqlbase import sqlvalues
+from lp.services.database.interfaces import IStore
 from lp.soyuz.interfaces.distroarchseriesbinarypackagerelease import (
     IDistroArchSeriesBinaryPackageRelease,
     )
@@ -87,33 +88,40 @@ class DistroArchSeriesBinaryPackageRelease:
 # content classes in order to be better maintained. In this specific case
 # the publishing queries should live in publishing.py.
     def _latest_publishing_record(self, status=None):
-        query = """
-            binarypackagerelease = %s AND
-            distroarchseries = %s AND
-            archive IN %s
-        """ % sqlvalues(self.binarypackagerelease, self.distroarchseries,
-                        self.distribution.all_distro_archive_ids)
+        clauses = [
+            BinaryPackagePublishingHistory.binarypackagerelease ==
+                self.binarypackagerelease,
+            BinaryPackagePublishingHistory.distroarchseries ==
+                self.distroarchseries,
+            BinaryPackagePublishingHistory.archiveID.is_in(
+                self.distribution.all_distro_archive_ids),
+            ]
 
         if status is not None:
             if not isinstance(status, (tuple, list)):
                 status = [status]
-            query += " AND status IN %s" % sqlvalues(status)
+            clauses.append(BinaryPackagePublishingHistory.status.is_in(status))
 
-        return BinaryPackagePublishingHistory.selectFirst(
-            query, orderBy=['-datecreated', '-id'])
+        return IStore(BinaryPackagePublishingHistory).find(
+            BinaryPackagePublishingHistory,
+            *clauses).order_by(
+                Desc(BinaryPackagePublishingHistory.datecreated),
+                Desc(BinaryPackagePublishingHistory.id)).first()
 
     @property
     def publishing_history(self):
         """See `IDistroArchSeriesBinaryPackage`."""
-        return BinaryPackagePublishingHistory.select("""
-            distroarchseries = %s AND
-            archive IN %s AND
-            binarypackagerelease = %s
-            """ % sqlvalues(
-                    self.distroarchseries,
-                    self.distribution.all_distro_archive_ids,
-                    self.binarypackagerelease),
-            orderBy=['-datecreated', '-id'])
+        return IStore(BinaryPackagePublishingHistory).find(
+            BinaryPackagePublishingHistory,
+            BinaryPackagePublishingHistory.distroarchseries ==
+                self.distroarchseries,
+            BinaryPackagePublishingHistory.archiveID.is_in(
+                self.distribution.all_distro_archive_ids),
+            BinaryPackagePublishingHistory.binarypackagerelease ==
+                self.binarypackagerelease,
+            ).order_by(
+                Desc(BinaryPackagePublishingHistory.datecreated),
+                Desc(BinaryPackagePublishingHistory.id))
 
     @property
     def pocket(self):
diff --git a/lib/lp/soyuz/scripts/gina/handlers.py b/lib/lp/soyuz/scripts/gina/handlers.py
index 99c8166..654b6e6 100644
--- a/lib/lp/soyuz/scripts/gina/handlers.py
+++ b/lib/lp/soyuz/scripts/gina/handlers.py
@@ -45,6 +45,7 @@ from lp.registry.model.distribution import Distribution
 from lp.registry.model.distroseries import DistroSeries
 from lp.registry.model.sourcepackagename import SourcePackageName
 from lp.services.database.constants import UTC_NOW
+from lp.services.database.interfaces import IStore
 from lp.services.database.sqlbase import (
     quote,
     sqlvalues,
@@ -711,18 +712,17 @@ class SourcePackagePublisher:
 
     def _checkPublishing(self, sourcepackagerelease):
         """Query for the publishing entry"""
-        ret = SourcePackagePublishingHistory.select("""
-            sourcepackagerelease = %s AND
-            distroseries = %s AND
-            archive = %s AND
-            status in %s""" % sqlvalues(
-                sourcepackagerelease, self.distroseries,
-                self.distroseries.main_archive, active_publishing_status),
-            orderBy=["-datecreated"])
-        ret = list(ret)
-        if ret:
-            return ret[0]
-        return None
+        return IStore(SourcePackagePublishingHistory).find(
+            SourcePackagePublishingHistory,
+            SourcePackagePublishingHistory.sourcepackagerelease ==
+                sourcepackagerelease,
+            SourcePackagePublishingHistory.distroseries ==
+                self.distroseries,
+            SourcePackagePublishingHistory.archive ==
+                self.distroseries.main_archive,
+            SourcePackagePublishingHistory.status.is_in(
+                active_publishing_status),
+            ).order_by(SourcePackagePublishingHistory).last()
 
 
 class BinaryPackageHandler:
@@ -965,15 +965,14 @@ class BinaryPackagePublisher:
 
     def _checkPublishing(self, binarypackage):
         """Query for the publishing entry"""
-        ret = BinaryPackagePublishingHistory.select("""
-            binarypackagerelease = %s AND
-            distroarchseries = %s AND
-            archive = %s AND
-            status in %s""" % sqlvalues(
-                binarypackage, self.distroarchseries,
-                self.distroarchseries.main_archive, active_publishing_status),
-            orderBy=["-datecreated"])
-        ret = list(ret)
-        if ret:
-            return ret[0]
-        return None
+        return IStore(BinaryPackagePublishingHistory).find(
+            BinaryPackagePublishingHistory,
+            BinaryPackagePublishingHistory.binarypackagerelease ==
+                binarypackage,
+            BinaryPackagePublishingHistory.distroarchseries ==
+                self.distroarchseries,
+            BinaryPackagePublishingHistory.archive ==
+                self.distroarchseries.main_archive,
+            BinaryPackagePublishingHistory.status.is_in(
+                active_publishing_status),
+            ).order_by(BinaryPackagePublishingHistory.datecreated).last()
diff --git a/lib/lp/soyuz/scripts/tests/test_obsoletedistroseries.py b/lib/lp/soyuz/scripts/tests/test_obsoletedistroseries.py
index 02e73ca..2dbd468 100644
--- a/lib/lp/soyuz/scripts/tests/test_obsoletedistroseries.py
+++ b/lib/lp/soyuz/scripts/tests/test_obsoletedistroseries.py
@@ -12,9 +12,10 @@ from zope.component import getUtility
 from lp.registry.interfaces.distribution import IDistributionSet
 from lp.registry.interfaces.series import SeriesStatus
 from lp.services.config import config
-from lp.services.database.sqlbase import sqlvalues
+from lp.services.database.interfaces import IStore
 from lp.services.log.logger import DevNullLogger
 from lp.soyuz.enums import PackagePublishingStatus
+from lp.soyuz.model.distroarchseries import DistroArchSeries
 from lp.soyuz.model.publishing import (
     BinaryPackagePublishingHistory,
     SourcePackagePublishingHistory,
@@ -106,22 +107,22 @@ class TestObsoleteDistroseries(TestCaseWithFactory):
         """Return a tuple of sources, binaries published in distroseries."""
         if distroseries is None:
             distroseries = self.warty
-        published_sources = SourcePackagePublishingHistory.select("""
-            distroseries = %s AND
-            status = %s AND
-            archive IN %s
-            """ % sqlvalues(distroseries, PackagePublishingStatus.PUBLISHED,
-                            self.main_archive_ids))
-        published_binaries = BinaryPackagePublishingHistory.select("""
-            BinaryPackagePublishingHistory.distroarchseries =
-                DistroArchSeries.id AND
-            DistroArchSeries.DistroSeries = DistroSeries.id AND
-            DistroSeries.id = %s AND
-            BinaryPackagePublishingHistory.status = %s AND
-            BinaryPackagePublishingHistory.archive IN %s
-            """ % sqlvalues(distroseries, PackagePublishingStatus.PUBLISHED,
-                            self.main_archive_ids),
-            clauseTables=["DistroArchSeries", "DistroSeries"])
+        published_sources = IStore(SourcePackagePublishingHistory).find(
+            SourcePackagePublishingHistory,
+            SourcePackagePublishingHistory.distroseries == distroseries,
+            SourcePackagePublishingHistory.status ==
+                PackagePublishingStatus.PUBLISHED,
+            SourcePackagePublishingHistory.archiveID.is_in(
+                self.main_archive_ids))
+        published_binaries = IStore(BinaryPackagePublishingHistory).find(
+            BinaryPackagePublishingHistory,
+            BinaryPackagePublishingHistory.distroarchseries ==
+                DistroArchSeries.id,
+            DistroArchSeries.distroseries == distroseries,
+            BinaryPackagePublishingHistory.status ==
+                PackagePublishingStatus.PUBLISHED,
+            BinaryPackagePublishingHistory.archiveID.is_in(
+                self.main_archive_ids))
         return (published_sources, published_binaries)
 
     def testNonObsoleteDistroseries(self):
@@ -163,13 +164,14 @@ class TestObsoleteDistroseries(TestCaseWithFactory):
         # Now see if the modified publications have been correctly obsoleted.
         # We need to re-fetch the published_sources and published_binaries
         # because the existing objects are not valid through a transaction.
+        store = IStore(SourcePackagePublishingHistory)
         for id in source_ids:
-            source = SourcePackagePublishingHistory.get(id)
+            source = store.get(SourcePackagePublishingHistory, id)
             self.assertTrue(
                 source.status == PackagePublishingStatus.OBSOLETE)
             self.assertTrue(source.scheduleddeletiondate is not None)
         for id in binary_ids:
-            binary = BinaryPackagePublishingHistory.get(id)
+            binary = store.get(BinaryPackagePublishingHistory, id)
             self.assertTrue(
                 binary.status == PackagePublishingStatus.OBSOLETE)
             self.assertTrue(binary.scheduleddeletiondate is not None)
@@ -177,8 +179,8 @@ class TestObsoleteDistroseries(TestCaseWithFactory):
         # Make sure nothing else was obsoleted.  Subtract the set of
         # known OBSOLETE IDs from the set of all the IDs and assert that
         # the remainder are not OBSOLETE.
-        all_sources = SourcePackagePublishingHistory.select(True)
-        all_binaries = BinaryPackagePublishingHistory.select(True)
+        all_sources = store.find(SourcePackagePublishingHistory)
+        all_binaries = store.find(BinaryPackagePublishingHistory)
         all_source_ids = [source.id for source in all_sources]
         all_binary_ids = [binary.id for binary in all_binaries]
 
@@ -186,11 +188,11 @@ class TestObsoleteDistroseries(TestCaseWithFactory):
         remaining_binary_ids = set(all_binary_ids) - set(binary_ids)
 
         for id in remaining_source_ids:
-            source = SourcePackagePublishingHistory.get(id)
+            source = store.get(SourcePackagePublishingHistory, id)
             self.assertTrue(
                 source.status != PackagePublishingStatus.OBSOLETE)
         for id in remaining_binary_ids:
-            binary = BinaryPackagePublishingHistory.get(id)
+            binary = store.get(BinaryPackagePublishingHistory, id)
             self.assertTrue(
                 binary.status != PackagePublishingStatus.OBSOLETE)