← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~stevenk/launchpad/more-fti_search into lp:launchpad

 

Steve Kowalik has proposed merging lp:~stevenk/launchpad/more-fti_search into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~stevenk/launchpad/more-fti_search/+merge/174342

Banish use of SQL(<table>.fti) by switching to fti_search (and rank_by_fti in a few cases). There a few callsites that still construct FTI expressions as strings, but I left those alone until they can be Stormed.
-- 
https://code.launchpad.net/~stevenk/launchpad/more-fti_search/+merge/174342
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~stevenk/launchpad/more-fti_search into lp:launchpad.
=== modified file 'lib/lp/bugs/browser/tests/bugtask-adding-views.txt'
--- lib/lp/bugs/browser/tests/bugtask-adding-views.txt	2012-05-24 20:25:54 +0000
+++ lib/lp/bugs/browser/tests/bugtask-adding-views.txt	2013-07-12 06:33:39 +0000
@@ -518,7 +518,7 @@
 
     >>> flush_database_updates()
     >>> dummy = form.pop('create_new')
-    >>> form['field.name'] = 'foo'
+    >>> form['field.name'] = u'foo'
     >>> form['field.displayname'] = 'Foo, the return'
     >>> form['field.summary'] = 'Foo'
     >>> add_task_view = create_view(

=== modified file 'lib/lp/bugs/model/cve.py'
--- lib/lp/bugs/model/cve.py	2013-01-07 02:40:55 +0000
+++ lib/lp/bugs/model/cve.py	2013-07-12 06:33:39 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2013 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 __metaclass__ = type
@@ -37,10 +37,8 @@
 from lp.services.database.constants import UTC_NOW
 from lp.services.database.datetimecol import UtcDateTimeCol
 from lp.services.database.enumcol import EnumCol
-from lp.services.database.sqlbase import (
-    SQLBase,
-    sqlvalues,
-    )
+from lp.services.database.sqlbase import SQLBase
+from lp.services.database.stormexpr import fti_search
 
 
 cverefpat = re.compile(r'(CVE|CAN)-((19|20)\d{2}\-\d{4})')
@@ -142,8 +140,8 @@
 
     def search(self, text):
         """See ICveSet."""
-        query = "Cve.fti @@ ftq(%s) " % sqlvalues(text)
-        return Cve.select(query, distinct=True, orderBy='-datemodified')
+        return Cve.select(
+            fti_search(Cve, text), distinct=True, orderBy='-datemodified')
 
     def inText(self, text):
         """See ICveSet."""

=== modified file 'lib/lp/registry/model/distribution.py'
--- lib/lp/registry/model/distribution.py	2013-06-20 05:50:00 +0000
+++ lib/lp/registry/model/distribution.py	2013-07-12 06:33:39 +0000
@@ -1020,12 +1020,9 @@
             DistributionSourcePackageCache.archiveID.is_in(
                 self.all_distro_archive_ids),
             Or(
-                SQL("DistributionSourcePackageCache.fti @@ ftq(?)",
-                    params=(text,)),
+                fti_search(DistributionSourcePackageCache, text),
                 DistributionSourcePackageCache.name.contains_string(
-                    text.lower()),
-                ),
-            ]
+                    text.lower()))]
 
         if has_packaging is not None:
             packaging_query = Exists(Select(

=== modified file 'lib/lp/registry/model/distroseries.py'
--- lib/lp/registry/model/distroseries.py	2013-06-20 05:50:00 +0000
+++ lib/lp/registry/model/distroseries.py	2013-07-12 06:33:39 +0000
@@ -103,6 +103,7 @@
     SQLBase,
     sqlvalues,
     )
+from lp.services.database.stormexpr import fti_search
 from lp.services.librarian.interfaces import ILibraryFileAliasSet
 from lp.services.librarian.model import LibraryFileAlias
 from lp.services.mail.signedmessage import signed_message_from_string
@@ -1089,7 +1090,7 @@
             DistroSeriesPackageCache.archiveID.is_in(
                 self.distribution.all_distro_archive_ids),
             Or(
-                SQL("DistroSeriesPackageCache.fti @@ ftq(?)", params=(text,)),
+                fti_search(DistroSeriesPackageCache, text),
                 DistroSeriesPackageCache.name.contains_string(text.lower())),
             ).config(distinct=True)
 

=== modified file 'lib/lp/registry/model/person.py'
--- lib/lp/registry/model/person.py	2013-06-21 02:49:33 +0000
+++ lib/lp/registry/model/person.py	2013-07-12 06:33:39 +0000
@@ -253,6 +253,7 @@
     SQLBase,
     sqlvalues,
     )
+from lp.services.database.stormexpr import fti_search
 from lp.services.helpers import (
     ensure_unicode,
     shortlist,
@@ -1130,7 +1131,7 @@
                 Or(
                     Product.name.contains_string(match_name),
                     Product.displayname.contains_string(match_name),
-                    SQL("Product.fti @@ ftq(?)", params=(match_name,))))
+                    fti_search(Product, match_name)))
         return IStore(Product).find(
             Product, *clauses
             ).config(distinct=True).order_by(Product.displayname)
@@ -3519,9 +3520,8 @@
         """Produce the query for team names."""
         team_name_query = And(
             get_person_visibility_terms(getUtility(ILaunchBag).user),
-            Person.teamowner != None,
-            Person.merged == None,
-            SQL("Person.fti @@ ftq(?)", (text, )))
+            Person.teamowner != None, Person.merged == None,
+            fti_search(Person, text))
         return team_name_query
 
     def find(self, text=""):
@@ -3556,12 +3556,10 @@
             Person, person_email_query).order_by()
 
         person_name_query = And(
-            Person.teamowner == None,
-            Person.merged == None,
+            Person.teamowner == None, Person.merged == None,
             Person.account == Account.id,
             Not(Account.status.is_in(INACTIVE_ACCOUNT_STATUSES)),
-            SQL("Person.fti @@ ftq(?)", (text, ))
-            )
+            fti_search(Person, text))
 
         results = results.union(store.find(
             Person, person_name_query)).order_by()
@@ -3621,9 +3619,7 @@
             EmailAddress.person == Person.id,
             EmailAddress.email.lower().startswith(text.lower()))
 
-        name_query = And(
-            base_query,
-            SQL("Person.fti @@ ftq(?)", (text, )))
+        name_query = And(base_query, fti_search(Person, text))
         email_results = store.find(Person, email_query).order_by()
         name_results = store.find(Person, name_query).order_by()
         combined_results = email_results.union(name_results)

=== modified file 'lib/lp/registry/model/product.py'
--- lib/lp/registry/model/product.py	2013-06-20 05:50:00 +0000
+++ lib/lp/registry/model/product.py	2013-07-12 06:33:39 +0000
@@ -194,6 +194,7 @@
     SQLBase,
     sqlvalues,
     )
+from lp.services.database.stormexpr import fti_search
 from lp.services.propertycache import (
     cachedproperty,
     get_property_cache,
@@ -1995,11 +1996,9 @@
     @classmethod
     def search(cls, user=None, text=None):
         """See lp.registry.interfaces.product.IProductSet."""
-        conditions = [Product.active,
-                      cls.getProductPrivacyFilter(user)]
+        conditions = [Product.active, cls.getProductPrivacyFilter(user)]
         if text:
-            conditions.append(
-                SQL("Product.fti @@ ftq(%s) " % sqlvalues(text)))
+            conditions.append(fti_search(Product, text))
         result = IStore(Product).find(Product, *conditions)
 
         def eager_load(products):

=== modified file 'lib/lp/soyuz/doc/vocabularies.txt'
--- lib/lp/soyuz/doc/vocabularies.txt	2012-12-26 01:32:19 +0000
+++ lib/lp/soyuz/doc/vocabularies.txt	2013-07-12 06:33:39 +0000
@@ -214,15 +214,15 @@
     ...         term = vocabulary.toTerm(archive)
     ...         print '%s: %s' % (term.token, term.title)
 
-    >>> cprov_search = vocabulary.search('cprov')
+    >>> cprov_search = vocabulary.search(u'cprov')
     >>> print_search_results(cprov_search)
     cprov/ppa: packages to help my friends.
 
-    >>> celso_search = vocabulary.search('celso')
+    >>> celso_search = vocabulary.search(u'celso')
     >>> print_search_results(celso_search)
     cprov/ppa: packages to help my friends.
 
-    >>> friends_search = vocabulary.search('friends')
+    >>> friends_search = vocabulary.search(u'friends')
     >>> print_search_results(friends_search)
     cprov/ppa: packages to help my friends.
 
@@ -240,7 +240,7 @@
 Now, a search for 'cprov' will return 2 ppas and the result is ordered
 by PPA name.
 
-    >>> cprov_search = vocabulary.search('cprov')
+    >>> cprov_search = vocabulary.search(u'cprov')
     >>> print_search_results(cprov_search)
     cprov/ppa: packages to help my friends.
     cprov/testing: testing packages.
@@ -248,7 +248,7 @@
 The vocabulary search also supports specific named PPA lookups
 follwing the same combined syntax used to build unique tokens.
 
-    >>> named_search = vocabulary.search('cprov/testing')
+    >>> named_search = vocabulary.search(u'cprov/testing')
     >>> print_search_results(named_search)
     cprov/testing: testing packages.
 
@@ -280,6 +280,6 @@
 
 Queries on empty strings also results in a valid SelectResults.
 
-    >>> empty_search = vocabulary.search('')
+    >>> empty_search = vocabulary.search(u'')
     >>> empty_search.count() == 0
     True

=== modified file 'lib/lp/soyuz/model/distroarchseries.py'
--- lib/lp/soyuz/model/distroarchseries.py	2013-06-24 15:49:51 +0000
+++ lib/lp/soyuz/model/distroarchseries.py	2013-07-12 06:33:39 +0000
@@ -18,9 +18,9 @@
     StringCol,
     )
 from storm.locals import (
+    Desc,
     Join,
     Or,
-    SQL,
     )
 from storm.store import EmptyResultSet
 from zope.component import getUtility
@@ -36,6 +36,10 @@
     SQLBase,
     sqlvalues,
     )
+from lp.services.database.stormexpr import (
+    fti_search,
+    rank_by_fti,
+    )
 from lp.services.helpers import shortlist
 from lp.services.librarian.interfaces import ILibraryFileAliasSet
 from lp.services.webapp.publisher import (
@@ -214,9 +218,7 @@
             find_spec = (
                 BinaryPackageRelease,
                 BinaryPackageName,
-                SQL("rank(BinaryPackageRelease.fti, ftq(%s)) AS rank" %
-                    sqlvalues(text))
-                )
+                rank_by_fti(BinaryPackageRelease, text))
         else:
             find_spec = (
                 BinaryPackageRelease,
@@ -228,20 +230,16 @@
         clauses = [
             BinaryPackagePublishingHistory.distroarchseries == self,
             BinaryPackagePublishingHistory.archiveID.is_in(archives),
-            BinaryPackagePublishingHistory.dateremoved == None,
-            ]
+            BinaryPackagePublishingHistory.dateremoved == None]
+        order_by = [BinaryPackageName.name]
         if text:
             clauses.append(
                 Or(
-                    SQL("BinaryPackageRelease.fti @@ ftq(?)", params=(text,)),
+                    fti_search(BinaryPackageRelease, text),
                     BinaryPackageName.name.contains_string(text.lower())))
+            order_by.insert(0, Desc(rank_by_fti(BinaryPackageRelease, text)))
         result = IStore(BinaryPackageName).using(*origin).find(
-            find_spec, *clauses).config(distinct=True)
-
-        if text:
-            result = result.order_by("rank DESC, BinaryPackageName.name")
-        else:
-            result = result.order_by("BinaryPackageName.name")
+            find_spec, *clauses).config(distinct=True).order_by(*order_by)
 
         # import here to avoid circular import problems
         from lp.soyuz.model.distroarchseriesbinarypackagerelease import (

=== modified file 'lib/lp/soyuz/vocabularies.py'
--- lib/lp/soyuz/vocabularies.py	2012-06-19 22:57:09 +0000
+++ lib/lp/soyuz/vocabularies.py	2013-07-12 06:33:39 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2011 Canonical Ltd.  This software is licensed under the GNU
+# Copyright 2009-2013 Canonical Ltd.  This software is licensed under the GNU
 # Affero General Public License version 3 (see the file LICENSE).
 
 """Soyuz vocabularies."""
@@ -14,17 +14,18 @@
     'ProcessorVocabulary',
     ]
 
-from sqlobject import AND
-from storm.expr import SQL
+from storm.locals import (
+    And,
+    Or,
+    )
 from zope.component import getUtility
 from zope.interface import implements
 from zope.schema.vocabulary import SimpleTerm
 
+from lp.registry.model.distroseries import DistroSeries
 from lp.registry.model.person import Person
-from lp.services.database.sqlbase import (
-    quote,
-    sqlvalues,
-    )
+from lp.services.database.interfaces import IStore
+from lp.services.database.stormexpr import fti_search
 from lp.services.webapp.interfaces import ILaunchBag
 from lp.services.webapp.vocabulary import (
     IHugeVocabulary,
@@ -56,7 +57,6 @@
 
     _table = DistroArchSeries
     _orderBy = ['DistroSeries.version', 'architecturetag', 'id']
-    _clauseTables = ['DistroSeries']
 
     def toTerm(self, obj):
         name = "%s %s (%s)" % (obj.distroseries.distribution.name,
@@ -66,12 +66,11 @@
     def __iter__(self):
         distribution = getUtility(ILaunchBag).distribution
         if distribution:
-            query = """
-                DistroSeries.id = DistroArchSeries.distroseries AND
-                DistroSeries.distribution = %s
-                """ % sqlvalues(distribution.id)
-            results = self._table.select(
-                query, orderBy=self._orderBy, clauseTables=self._clauseTables)
+            results = IStore(DistroSeries).find(
+                self._table,
+                DistroSeries.id == DistroArchSeries.distroseriesID,
+                DistroSeries.distributionID == distribution.id).orderBy(
+                    *self._orderBy)
             for distroarchseries in results:
                 yield self.toTerm(distroarchseries)
 
@@ -92,7 +91,7 @@
     _table = Archive
     _orderBy = ['Person.name, Archive.name']
     _clauseTables = ['Person']
-    _filter = AND(
+    _filter = And(
         Person.q.id == Archive.q.ownerID,
         Archive.q.purpose == ArchivePurpose.PPA)
     displayname = 'Select a PPA'
@@ -117,7 +116,7 @@
         except ValueError:
             raise LookupError(token)
 
-        clause = AND(
+        clause = And(
             self._filter,
             Person.name == owner_name,
             Archive.name == archive_name)
@@ -143,14 +142,12 @@
         try:
             owner_name, archive_name = query.split('/')
         except ValueError:
-            clause = AND(
+            clause = And(
                 self._filter,
-                SQL("(Archive.fti @@ ftq(%s) OR Person.fti @@ ftq(%s))"
-                    % (quote(query), quote(query))))
+                Or(fti_search(Archive, query), fti_search(Person, query)))
         else:
-            clause = AND(
-                self._filter,
-                Person.name == owner_name,
+            clause = And(
+                self._filter, Person.name == owner_name,
                 Archive.name == archive_name)
 
         return self._table.select(