William Grant has proposed merging lp:~wgrant/launchpad/bug-816870 into
lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~wgrant/launchpad/bug-816870/+merge/108728
This branch hopefully fixes the parts of Distribution:+search that contribute
most to its almost unending timeouts.
Firstly, has_exact_matches no longer does a slow count(). is_empty() is fine
for its purposes. Secondly, searchBinaryPackages has its extremely hideous and
slow 8 table join replaced with a slightly less hideous but 50x faster set of
LIKEs.
DistributionSourcePackageCache.binpkgnames is a space-separated string of all
the binaries produced by the source. We'd ideally replace it with something
like an array of SPN IDs, but schema changes like that aren't quite cheap yet,
so I achieve an exact match by forcing there to be a word boundary on both
sides of the name. A regular expression would be a lot prettier, but it ended
up being 300ms vs 90ms, so I decided the LIKEs won for now.
--
https://code.launchpad.net/~wgrant/launchpad/bug-816870/+merge/108728
Your team Launchpad code reviewers is requested to review the proposed merge of
lp:~wgrant/launchpad/bug-816870 into lp:launchpad.
=== modified file 'lib/lp/registry/browser/distribution.py'
--- lib/lp/registry/browser/distribution.py 2012-05-18 07:51:18 +0000
+++ lib/lp/registry/browser/distribution.py 2012-06-05 12:36:21 +0000
@@ -585,7 +585,7 @@
@property
def has_exact_matches(self):
- return self.exact_matches.count() > 0
+ return not self.exact_matches.is_empty()
@property
def has_matches(self):
=== modified file 'lib/lp/registry/model/distribution.py'
--- lib/lp/registry/model/distribution.py 2012-05-14 13:32:03 +0000
+++ lib/lp/registry/model/distribution.py 2012-06-05 12:36:21 +0000
@@ -179,7 +179,6 @@
from lp.soyuz.interfaces.buildrecords import IHasBuildRecords
from lp.soyuz.interfaces.publishing import active_publishing_status
from lp.soyuz.model.archive import Archive
-from lp.soyuz.model.binarypackagebuild import BinaryPackageBuild
from lp.soyuz.model.binarypackagename import BinaryPackageName
from lp.soyuz.model.binarypackagerelease import BinaryPackageRelease
from lp.soyuz.model.distributionsourcepackagerelease import (
@@ -1167,52 +1166,39 @@
# results will only see DSPs
return DecoratedResultSet(dsp_caches_with_ranks, result_to_dsp)
- @property
- def _binaryPackageSearchClause(self):
- """Return a Storm match clause for binary package searches."""
- # This matches all DistributionSourcePackageCache rows that have
- # a source package that generated the BinaryPackageName that
- # we're searching for.
+ def searchBinaryPackages(self, package_name, exact_match=False):
+ """See `IDistribution`."""
from lp.soyuz.model.distributionsourcepackagecache import (
DistributionSourcePackageCache,
)
- return (
- DistroSeries.distribution == self,
- DistroSeries.status != SeriesStatus.OBSOLETE,
- DistroArchSeries.distroseries == DistroSeries.id,
- BinaryPackageBuild.distro_arch_series == DistroArchSeries.id,
- BinaryPackageRelease.build == BinaryPackageBuild.id,
- (BinaryPackageBuild.source_package_release ==
- SourcePackageRelease.id),
- SourcePackageRelease.sourcepackagename == SourcePackageName.id,
- DistributionSourcePackageCache.sourcepackagename ==
- SourcePackageName.id,
+ store = Store.of(self)
+
+ select_spec = (DistributionSourcePackageCache,)
+
+ find_spec = (
+ DistributionSourcePackageCache.distribution == self,
DistributionSourcePackageCache.archiveID.is_in(
self.all_distro_archive_ids))
- def searchBinaryPackages(self, package_name, exact_match=False):
- """See `IDistribution`."""
- from lp.soyuz.model.distributionsourcepackagecache import (
- DistributionSourcePackageCache,
- )
- store = Store.of(self)
-
- select_spec = (DistributionSourcePackageCache,)
-
if exact_match:
- find_spec = self._binaryPackageSearchClause + (
- BinaryPackageRelease.binarypackagename
- == BinaryPackageName.id,
- )
- match_clause = (BinaryPackageName.name == package_name,)
+ # To match BinaryPackageName.name exactly requires a very
+ # slow 8 table join. So let's instead use binpkgnames, with
+ # an ugly set of LIKEs matching spaces or either end of the
+ # string on either side of the name. A regex is several
+ # times slower and harder to escape.
+ match_clause = (Or(
+ DistributionSourcePackageCache.binpkgnames.like(
+ '%% %s %%' % package_name.lower()),
+ DistributionSourcePackageCache.binpkgnames.like(
+ '%% %s' % package_name.lower()),
+ DistributionSourcePackageCache.binpkgnames.like(
+ '%s %%' % package_name.lower()),
+ DistributionSourcePackageCache.binpkgnames ==
+ package_name.lower()), )
else:
# In this case we can use a simplified find-spec as the
# binary package names are present on the
# DistributionSourcePackageCache records.
- find_spec = (
- DistributionSourcePackageCache.distribution == self,
- DistributionSourcePackageCache.archiveID.is_in(
- self.all_distro_archive_ids))
match_clause = (
DistributionSourcePackageCache.binpkgnames.like(
"%%%s%%" % package_name.lower()),)
=== modified file 'lib/lp/soyuz/browser/tests/distribution-views.txt'
--- lib/lp/soyuz/browser/tests/distribution-views.txt 2011-05-16 11:20:41 +0000
+++ lib/lp/soyuz/browser/tests/distribution-views.txt 2012-06-05 12:36:21 +0000
@@ -195,9 +195,9 @@
>>> distro_pkg_search_view.distroseries_names
{u'mozilla-firefox': u'warty'}
>>> distro_pkg_search_view = create_initialized_view(
- ... ubuntu, name="+search", form={'text': 'foobar'})
+ ... ubuntu, name="+search", form={'text': 'mozilla-firefox'})
>>> distro_pkg_search_view.distroseries_names
- {u'foobar': ''}
+ {u'mozilla-firefox': u'warty'}
Another helper on the DistributionPackageSearchView is the
matching_binary_names property which can be used by templates to get
_______________________________________________
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : [email protected]
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help : https://help.launchpad.net/ListHelp