Skip to content

Commit 14ceade

Browse files
author
Richard Jones
committed
fix anydbm sort/group direction handling...
...and make RDBMS sort/group use Link'ed "order" properties [SF#953148]
1 parent ee7e0c4 commit 14ceade

File tree

5 files changed

+90
-20
lines changed

5 files changed

+90
-20
lines changed

CHANGES.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ Fixed:
1010
- mention DEFAULT_TIMEZONE requirement in upgrading doc (sf bug 952932)
1111
- fix DateHTMLProperty so local() can override user timezone (sf bug
1212
953678)
13+
- fix anydbm sort/group direction handling, and make RDBMS sort/group use
14+
Link'ed "order" properties (sf bug 953148)
1315

1416

1517
2004-05-07 0.7.1

roundup/backends/back_anydbm.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
1616
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1717
#
18-
#$Id: back_anydbm.py,v 1.146.2.1 2004-05-12 22:28:21 richard Exp $
18+
#$Id: back_anydbm.py,v 1.146.2.2 2004-05-16 09:33:13 richard Exp $
1919
'''This module defines a backend that saves the hyperdatabase in a
2020
database chosen by anydbm. It is guaranteed to always be available in python
2121
versions >2.1.1 (the dumbdbm fallback in 2.1.1 and earlier has several
@@ -1800,21 +1800,27 @@ def filter(self, search_matches, filterspec, sort=(None,None),
18001800
finally:
18011801
cldb.close()
18021802

1803+
# sort vals are inserted, but directions are appended, so reverse
1804+
directions.reverse()
1805+
18031806
if '-' in directions:
18041807
# one or more of the sort specs is in reverse order, so we have
18051808
# to use this icky function to sort
18061809
def sortfun(a, b, directions=directions, n=range(len(directions))):
18071810
for i in n:
1808-
if a[i] == b[i]: continue
1811+
if not cmp(a[i], b[i]):
1812+
continue
18091813
if directions[i] == '+':
1814+
# compare in the usual, ascending direction
18101815
return cmp(a[i],b[i])
18111816
else:
1817+
# compare in the reverse, descending direction
18121818
return cmp(b[i],a[i])
18131819
# for consistency, sort by the id if the items are equal
18141820
return cmp(a[-2], b[-2])
18151821
matches.sort(sortfun)
18161822
else:
1817-
# sorting is in the normal direction
1823+
# sorting is in the normal, ascending direction
18181824
matches.sort()
18191825

18201826
# pull the id out of the individual entries

roundup/backends/back_mysql.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,7 @@ def filter(self, search_matches, filterspec, sort=(None,None),
638638
args.append(v)
639639

640640
# don't match retired nodes
641-
where.append('__retired__ <> 1')
641+
where.append('_%s.__retired__ <> 1'%cn)
642642

643643
# add results of full text search
644644
if search_matches is not None:
@@ -661,6 +661,16 @@ def filter(self, search_matches, filterspec, sort=(None,None),
661661
# use the int column for sorting
662662
o = '__'+prop+'_int__'
663663
ordercols.append(o)
664+
elif isinstance(props[prop], Link):
665+
# determine whether the linked Class has an order property
666+
lcn = props[prop].classname
667+
link = self.db.classes[lcn]
668+
if link.getprops().has_key('order'):
669+
tn = '_' + lcn
670+
frum.append(tn)
671+
where.append('_%s._%s = %s.id'%(cn, prop, tn))
672+
ordercols.append(tn + '._order')
673+
o = tn + '._order'
664674
elif prop == 'id':
665675
o = 'id'
666676
else:
@@ -679,9 +689,9 @@ def filter(self, search_matches, filterspec, sort=(None,None),
679689
if mlfilt:
680690
# we're joining tables on the id, so we will get dupes if we
681691
# don't distinct()
682-
cols = ['distinct(id)']
692+
cols = ['distinct(_%s.id)'%cn]
683693
else:
684-
cols = ['id']
694+
cols = ['_%s.id'%cn]
685695
if orderby:
686696
cols = cols + ordercols
687697
order = ' order by %s'%(','.join(orderby))

roundup/backends/rdbms_common.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# $Id: rdbms_common.py,v 1.98.2.1 2004-05-10 01:27:59 richard Exp $
1+
# $Id: rdbms_common.py,v 1.98.2.2 2004-05-16 09:33:13 richard Exp $
22
''' Relational database (SQL) backend common code.
33
44
Basics:
@@ -2123,7 +2123,7 @@ def filter(self, search_matches, filterspec, sort=(None,None),
21232123
args.append(v)
21242124

21252125
# don't match retired nodes
2126-
where.append('__retired__ <> 1')
2126+
where.append('_%s.__retired__ <> 1'%cn)
21272127

21282128
# add results of full text search
21292129
if search_matches is not None:
@@ -2146,6 +2146,16 @@ def filter(self, search_matches, filterspec, sort=(None,None),
21462146
# use the int column for sorting
21472147
o = '__'+prop+'_int__'
21482148
ordercols.append(o)
2149+
elif isinstance(props[prop], Link):
2150+
# determine whether the linked Class has an order property
2151+
lcn = props[prop].classname
2152+
link = self.db.classes[lcn]
2153+
if link.getprops().has_key('order'):
2154+
tn = '_' + lcn
2155+
frum.append(tn)
2156+
where.append('_%s._%s = %s.id'%(cn, prop, tn))
2157+
ordercols.append(tn + '._order')
2158+
o = tn + '._order'
21492159
elif prop == 'id':
21502160
o = 'id'
21512161
else:
@@ -2164,9 +2174,9 @@ def filter(self, search_matches, filterspec, sort=(None,None),
21642174
if mlfilt:
21652175
# we're joining tables on the id, so we will get dupes if we
21662176
# don't distinct()
2167-
cols = ['distinct(id)']
2177+
cols = ['distinct(_%s.id)'%cn]
21682178
else:
2169-
cols = ['id']
2179+
cols = ['_%s.id'%cn]
21702180
if orderby:
21712181
cols = cols + ordercols
21722182
order = ' order by %s'%(','.join(orderby))

test/db_test_base.py

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
1616
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1717
#
18-
# $Id: db_test_base.py,v 1.27 2004-05-06 01:03:01 richard Exp $
18+
# $Id: db_test_base.py,v 1.27.2.1 2004-05-16 09:33:14 richard Exp $
1919

2020
import unittest, os, shutil, errno, imp, sys, time, pprint
2121

@@ -27,14 +27,17 @@
2727
def setupSchema(db, create, module):
2828
status = module.Class(db, "status", name=String())
2929
status.setkey("name")
30+
priority = module.Class(db, "priority", name=String(), order=String())
31+
priority.setkey("name")
3032
user = module.Class(db, "user", username=String(), password=Password(),
3133
assignable=Boolean(), age=Number(), roles=String())
3234
user.setkey("username")
3335
file = module.FileClass(db, "file", name=String(), type=String(),
3436
comment=String(indexme="yes"), fooz=Password())
3537
issue = module.IssueClass(db, "issue", title=String(indexme="yes"),
3638
status=Link("status"), nosy=Multilink("user"), deadline=Date(),
37-
foo=Interval(), files=Multilink("file"), assignedto=Link('user'))
39+
foo=Interval(), files=Multilink("file"), assignedto=Link('user'),
40+
priority=Link('priority'))
3841
stuff = module.Class(db, "stuff", stuff=String())
3942
session = module.Class(db, 'session', title=String())
4043
session.disableJournalling()
@@ -48,6 +51,9 @@ def setupSchema(db, create, module):
4851
status.create(name="in-progress")
4952
status.create(name="testing")
5053
status.create(name="resolved")
54+
priority.create(name="feature", order="2")
55+
priority.create(name="wish", order="3")
56+
priority.create(name="bug", order="1")
5157
db.commit()
5258

5359
class MyTestCase(unittest.TestCase):
@@ -814,15 +820,15 @@ def filteringSetup(self):
814820
iss = self.db.issue
815821
for issue in (
816822
{'title': 'issue one', 'status': '2', 'assignedto': '1',
817-
'foo': date.Interval('1:10'),
823+
'foo': date.Interval('1:10'), 'priority': '1',
818824
'deadline': date.Date('2003-01-01.00:00')},
819-
{'title': 'issue two', 'status': '1', 'assignedto': '2',
820-
'foo': date.Interval('1d'),
825+
{'title': 'issue two', 'status': '1', 'assignedto': '2',
826+
'foo': date.Interval('1d'), 'priority': '3',
821827
'deadline': date.Date('2003-02-16.22:50')},
822-
{'title': 'issue three', 'status': '1',
828+
{'title': 'issue three', 'status': '1', 'priority': '2',
823829
'nosy': ['1','2'], 'deadline': date.Date('2003-02-18')},
824830
{'title': 'non four', 'status': '3',
825-
'foo': date.Interval('0:10'),
831+
'foo': date.Interval('0:10'), 'priority': '1',
826832
'nosy': ['1'], 'deadline': date.Date('2004-03-08')}):
827833
self.db.issue.create(**issue)
828834
self.db.commit()
@@ -887,17 +893,53 @@ def testFilteringRange(self):
887893
ae(filt(None, {'foo': 'to 0:05'}), [])
888894

889895
def testFilteringIntervalSort(self):
896+
# 1: '1:10'
897+
# 2: '1d'
898+
# 3: None
899+
# 4: '0:10'
890900
ae, filt = self.filteringSetup()
891901
# ascending should sort None, 1:10, 1d
892902
ae(filt(None, {}, ('+','foo'), (None,None)), ['3', '4', '1', '2'])
893903
# descending should sort 1d, 1:10, None
894904
ae(filt(None, {}, ('-','foo'), (None,None)), ['2', '1', '4', '3'])
895905

896906
def testFilteringMultilinkSort(self):
907+
# 1: []
908+
# 2: []
909+
# 3: ['1','2']
910+
# 4: ['1']
897911
ae, filt = self.filteringSetup()
898912
ae(filt(None, {}, ('+','nosy'), (None,None)), ['1', '2', '4', '3'])
899913
ae(filt(None, {}, ('-','nosy'), (None,None)), ['3', '4', '1', '2'])
900914

915+
def testFilteringDateSort(self):
916+
# '1': '2003-01-01.00:00'
917+
# '2': '2003-02-16.22:50'
918+
# '3': '2003-02-18'
919+
# '4': '2004-03-08'
920+
ae, filt = self.filteringSetup()
921+
# ascending
922+
ae(filt(None, {}, ('+','deadline'), (None,None)), ['1', '2', '3', '4'])
923+
# descending
924+
ae(filt(None, {}, ('-','deadline'), (None,None)), ['4', '3', '2', '1'])
925+
926+
def testFilteringDateSortPriorityGroup(self):
927+
# '1': '2003-01-01.00:00' 1 => 2
928+
# '2': '2003-02-16.22:50' 3 => 1
929+
# '3': '2003-02-18' 2 => 3
930+
# '4': '2004-03-08' 1 => 2
931+
ae, filt = self.filteringSetup()
932+
# ascending
933+
ae(filt(None, {}, ('+','deadline'), ('+','priority')),
934+
['2', '1', '4', '3'])
935+
ae(filt(None, {}, ('-','deadline'), ('+','priority')),
936+
['2', '4', '1', '3'])
937+
# descending
938+
ae(filt(None, {}, ('+','deadline'), ('-','priority')),
939+
['3', '1', '4', '2'])
940+
ae(filt(None, {}, ('-','deadline'), ('-','priority')),
941+
['3', '4', '1', '2'])
942+
901943
# XXX add sorting tests for other types
902944
# XXX test auditors and reactors
903945

@@ -993,7 +1035,7 @@ def testAddProperty(self):
9931035
keys.sort()
9941036
self.assertEqual(keys, ['activity', 'actor', 'assignedto', 'creation',
9951037
'creator', 'deadline', 'files', 'fixer', 'foo', 'id', 'messages',
996-
'nosy', 'status', 'superseder', 'title'])
1038+
'nosy', 'priority', 'status', 'superseder', 'title'])
9971039
self.assertEqual(self.db.issue.get('1', "fixer"), None)
9981040

9991041
def testRemoveProperty(self):
@@ -1007,7 +1049,7 @@ def testRemoveProperty(self):
10071049
keys.sort()
10081050
self.assertEqual(keys, ['activity', 'actor', 'assignedto', 'creation',
10091051
'creator', 'deadline', 'files', 'foo', 'id', 'messages',
1010-
'nosy', 'status', 'superseder'])
1052+
'nosy', 'priority', 'status', 'superseder'])
10111053
self.assertEqual(self.db.issue.list(), ['1'])
10121054

10131055
def testAddRemoveProperty(self):
@@ -1022,7 +1064,7 @@ def testAddRemoveProperty(self):
10221064
keys.sort()
10231065
self.assertEqual(keys, ['activity', 'actor', 'assignedto', 'creation',
10241066
'creator', 'deadline', 'files', 'fixer', 'foo', 'id', 'messages',
1025-
'nosy', 'status', 'superseder'])
1067+
'nosy', 'priority', 'status', 'superseder'])
10261068
self.assertEqual(self.db.issue.list(), ['1'])
10271069

10281070
class ROTest(MyTestCase):

0 commit comments

Comments
 (0)