[Checkins] SVN: Products.ZCatalog/trunk/ Finish support for differing sort_order values for searches using two sort indexes
Hano Schlichting
cvs-admin at zope.org
Sat Apr 7 15:57:55 UTC 2012
Log message for revision 125082:
Finish support for differing sort_order values for searches using two sort indexes
Changed:
U Products.ZCatalog/trunk/CHANGES.txt
U Products.ZCatalog/trunk/src/Products/ZCatalog/Catalog.py
U Products.ZCatalog/trunk/src/Products/ZCatalog/tests/test_catalog.py
-=-
Modified: Products.ZCatalog/trunk/CHANGES.txt
===================================================================
--- Products.ZCatalog/trunk/CHANGES.txt 2012-04-07 14:42:22 UTC (rev 125081)
+++ Products.ZCatalog/trunk/CHANGES.txt 2012-04-07 15:57:52 UTC (rev 125082)
@@ -11,12 +11,13 @@
methods and used it for a progress handler. Also optimized some of their
internals.
-- Added support for simple `sort_on` queries with two sort indexes. The
- `sort_order` is currently single valued and applies to both of them. But a
- query like: `{'foo': 'a', 'sort_on':['foo', 'bar']}` is supported now.
+- Added support for simple `sort_on` queries with two sort indexes and
+ differing `sort_order` values. For example:
+ `{'foo': 'a', 'sort_on': ('foo', 'bar')}`
+ `{'foo': 'a', 'sort_on': ('foo', 'bar'), 'sort_order': ('', 'reverse')}`
- Change some internal wiring and let multiple sort_on values pass through.
- `Catalog.sortResults` is now called with a list of search indexes.
+ `Catalog.sortResults` can now be called with a list of search indexes.
- Added support for `not` queries in field and keyword indexes. Both
restrictions of normal queries and range queries are supported, as well as
Modified: Products.ZCatalog/trunk/src/Products/ZCatalog/Catalog.py
===================================================================
--- Products.ZCatalog/trunk/src/Products/ZCatalog/Catalog.py 2012-04-07 14:42:22 UTC (rev 125081)
+++ Products.ZCatalog/trunk/src/Products/ZCatalog/Catalog.py 2012-04-07 15:57:52 UTC (rev 125082)
@@ -692,7 +692,10 @@
# order and limit it, then reverse the result set again
switched_reverse = False
if b_size and b_start and b_start > rlen / 2:
- reverse = not reverse
+ if isinstance(reverse, list):
+ reverse = [not r for r in reverse]
+ else:
+ reverse = not reverse
switched_reverse = True
b_end = b_start + b_size
if b_end >= rlen:
@@ -708,7 +711,14 @@
limit = b_start + b_size
# determine sort_spec
- sort_spec = [reverse and -1 or 1, reverse and -1 or 1]
+ if isinstance(reverse, list):
+ sort_spec = [r and -1 or 1 for r in reverse]
+ # limit to current maximum of two indexes
+ sort_spec = sort_spec[:2]
+ # use first sort order for choosing the algorithm
+ reverse = reverse[0]
+ else:
+ sort_spec = [reverse and -1 or 1, reverse and -1 or 1]
if merge and limit is None and (
rlen > (len(sort_index) * (rlen / 100 + 1))):
@@ -921,9 +931,16 @@
reverse = False
if sort_indexes is not None:
order = self._get_sort_attr("order", args)
- if (isinstance(order, str) and
- order.lower() in ('reverse', 'descending')):
- reverse = True
+ reverse = []
+ if order is None:
+ order = ['']
+ elif isinstance(order, str):
+ order = [order]
+ for o in order:
+ reverse.append(o.lower() in ('reverse', 'descending'))
+ if len(reverse) == 1:
+ # be nice and keep the old API intact for single sort_order
+ reverse = reverse[0]
# Perform searches with indexes and sort_index
return self.search(args, sort_indexes, reverse, sort_limit, _merge)
@@ -1016,12 +1033,12 @@
list entry given via `items`.
"""
comparers = []
- for i in xrange(len(sort_spec)):
- comparers.append((itemgetter(i), sort_spec[i]))
+ for i, v in enumerate(sort_spec):
+ comparers.append((itemgetter(i), v))
def comparer(left, right):
for func, order in comparers:
- result = cmp(func(left), func(right))
+ result = cmp(func(left[0]), func(right[0]))
if result:
return order * result
return 0
Modified: Products.ZCatalog/trunk/src/Products/ZCatalog/tests/test_catalog.py
===================================================================
--- Products.ZCatalog/trunk/src/Products/ZCatalog/tests/test_catalog.py 2012-04-07 14:42:22 UTC (rev 125081)
+++ Products.ZCatalog/trunk/src/Products/ZCatalog/tests/test_catalog.py 2012-04-07 15:57:52 UTC (rev 125082)
@@ -471,6 +471,14 @@
self.assertEqual(result.actual_result_count, 100)
self.assertEqual([r.num for r in result], range(48, 56))
+ def testSortLimitViaBatchingArgsRightMiddleSortOnTwoSecond(self):
+ catalog = self._make_one()
+ query = dict(att1='att1', sort_on=('att1', 'num'),
+ sort_order=('', 'reverse'), b_start=48, b_size=8)
+ result = catalog(query)
+ self.assertEqual(result.actual_result_count, 100)
+ self.assertEqual([r.num for r in result], range(51, 43, -1))
+
def testSortLimitViaBatchingArgsEarlySecondHalf(self):
catalog = self._make_one()
query = dict(att1='att1', sort_on='num', b_start=55, b_size=15)
@@ -478,6 +486,30 @@
self.assertEqual(result.actual_result_count, 100)
self.assertEqual([r.num for r in result], range(55, 70))
+ def testSortLimitViaBatchingArgsEarlySecondHalfSortOnTwoFirst(self):
+ catalog = self._make_one()
+ query = dict(att1='att1', sort_on=('att1', 'num'),
+ sort_order=('reverse', ''), b_start=55, b_size=15)
+ result = catalog(query)
+ self.assertEqual(result.actual_result_count, 100)
+ self.assertEqual([r.num for r in result], range(55, 70))
+
+ def testSortLimitViaBatchingArgsEarlySecondHalfSortOnTwoSecond(self):
+ catalog = self._make_one()
+ query = dict(att1='att1', sort_on=('att1', 'num'),
+ sort_order=('', 'reverse'), b_start=55, b_size=15)
+ result = catalog(query)
+ self.assertEqual(result.actual_result_count, 100)
+ self.assertEqual([r.num for r in result], range(44, 29, -1))
+
+ def testSortLimitViaBatchingArgsEarlySecondHalfSortOnTwoBoth(self):
+ catalog = self._make_one()
+ query = dict(att1='att1', sort_on=('att1', 'num'),
+ sort_order=('reverse', 'reverse'), b_start=55, b_size=15)
+ result = catalog(query)
+ self.assertEqual(result.actual_result_count, 100)
+ self.assertEqual([r.num for r in result], range(44, 29, -1))
+
def testSortLimitViaBatchingArgsSecondHalf(self):
catalog = self._make_one()
query = dict(att1='att1', sort_on='num', b_start=70, b_size=15)
@@ -588,6 +620,51 @@
for x in range(upper - 1):
self.assertTrue(a[x].num > a[x + 1].num)
+ def test_sort_on_two_reverse_neither(self):
+ catalog = self._make_one()
+ upper = self.upper
+ a = catalog(sort_on=('att1', 'num'), att1='att1',
+ sort_order=('', ''))
+ self.assertEqual(len(a), upper)
+ for x in range(upper - 1):
+ self.assertTrue(a[x].num < a[x + 1].num)
+
+ def test_sort_on_two_reverse_first(self):
+ catalog = self._make_one()
+ upper = self.upper
+ a = catalog(sort_on=('att1', 'num'), att1='att1',
+ sort_order=('reverse', ''))
+ self.assertEqual(len(a), upper)
+ for x in range(upper - 1):
+ self.assertTrue(a[x].num < a[x + 1].num)
+
+ def test_sort_on_two_reverse_second(self):
+ catalog = self._make_one()
+ upper = self.upper
+ a = catalog(sort_on=('att1', 'num'), att1='att1',
+ sort_order=('', 'reverse'))
+ self.assertEqual(len(a), upper)
+ for x in range(upper - 1):
+ self.assertTrue(a[x].num > a[x + 1].num)
+
+ def test_sort_on_two_reverse_both(self):
+ catalog = self._make_one()
+ upper = self.upper
+ a = catalog(sort_on=('att1', 'num'), att1='att1',
+ sort_order=('reverse', 'reverse'))
+ self.assertEqual(len(a), upper)
+ for x in range(upper - 1):
+ self.assertTrue(a[x].num > a[x + 1].num)
+
+ def test_sort_on_two_reverse_too_many(self):
+ catalog = self._make_one()
+ upper = self.upper
+ a = catalog(sort_on=('att1', 'num'), att1='att1',
+ sort_order=('', '', 'reverse', ''))
+ self.assertEqual(len(a), upper)
+ for x in range(upper - 1):
+ self.assertTrue(a[x].num < a[x + 1].num)
+
def test_sort_on_two_small_limit(self):
catalog = self._make_one()
a = catalog(sort_on=('att1', 'num'), att1='att1', sort_limit=10)
More information about the checkins
mailing list