From 151d82b404c66112ef85f1dc81f0ff9c8ccc4f59 Mon Sep 17 00:00:00 2001 From: richard Date: Mon, 5 Apr 2004 07:13:10 +0000 Subject: [PATCH] sort/group by multilink in RDBMS git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@2256 57a73879-2fb5-44c3-a270-3262357dd7e2 --- CHANGES.txt | 1 + roundup/backends/rdbms_common.py | 68 ++++++++++++++++++-------------- test/db_test_base.py | 7 +++- 3 files changed, 46 insertions(+), 30 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index b116492..5f1a1e4 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -19,6 +19,7 @@ Fixed: download links (sf bug 927745) - all uses of TRACKER_WEB now ensure it ends with a '/' - roundup-admin install checks for existing tracker in target home +- grouping (and sorting) by multilink in RDBMS backends (sf bug 655702) 2004-03-27 0.7.0b2 diff --git a/roundup/backends/rdbms_common.py b/roundup/backends/rdbms_common.py index 657b477..ab43ecd 100644 --- a/roundup/backends/rdbms_common.py +++ b/roundup/backends/rdbms_common.py @@ -1,4 +1,4 @@ -# $Id: rdbms_common.py,v 1.88 2004-04-02 05:58:45 richard Exp $ +# $Id: rdbms_common.py,v 1.89 2004-04-05 07:13:10 richard Exp $ ''' Relational database (SQL) backend common code. Basics: @@ -2024,34 +2024,23 @@ class Class(hyperdb.Class): args = args + v # "grouping" is just the first-order sorting in the SQL fetch - # can modify it...) orderby = [] ordercols = [] - if group[0] is not None and group[1] is not None: - if group[0] != '-': - orderby.append('_'+group[1]) - ordercols.append('_'+group[1]) - else: - orderby.append('_'+group[1]+' desc') - ordercols.append('_'+group[1]) - - # now add in the sorting - group = '' - if sort[0] is not None and sort[1] is not None: - direction, colname = sort - if direction != '-': - if colname == 'id': - orderby.append(colname) - else: - orderby.append('_'+colname) - ordercols.append('_'+colname) - else: - if colname == 'id': - orderby.append(colname+' desc') - ordercols.append(colname) + mlsort = [] + for sortby in group, sort: + sdir, prop = sortby + if sdir and prop: + if isinstance(props[prop], Multilink): + mlsort.append(sortby) + continue + elif prop == 'id': + o = 'id' else: - orderby.append('_'+colname+' desc') - ordercols.append('_'+colname) + o = '_'+prop + ordercols.append(o) + if sdir == '-': + o += ' desc' + orderby.append(o) # construct the SQL frum = ','.join(frum) @@ -2059,14 +2048,14 @@ class Class(hyperdb.Class): where = ' where ' + (' and '.join(where)) else: where = '' - cols = ['id'] + cols = ['distinct(id)'] if orderby: cols = cols + ordercols order = ' order by %s'%(','.join(orderby)) else: order = '' cols = ','.join(cols) - sql = 'select %s from %s %s%s%s'%(cols, frum, where, group, order) + sql = 'select %s from %s %s%s'%(cols, frum, where, order) args = tuple(args) if __debug__: print >>hyperdb.DEBUG, 'filter', (self, sql, args) @@ -2079,7 +2068,28 @@ class Class(hyperdb.Class): # return the IDs (the first column) # XXX numeric ids - return [str(row[0]) for row in l] + l = [str(row[0]) for row in l] + + if not mlsort: + return l + + # ergh. someone wants to sort by a multilink. + r = [] + for id in l: + m = [] + for ml in mlsort: + m.append(self.get(id, ml[1])) + r.append((id, m)) + i = 0 + for sortby in mlsort: + def sortfun(a, b, dir=sortby[i]): + if dir == '-': + return cmp(b[1][i], a[1][i]) + else: + return cmp(a[1][i], b[1][i]) + r.sort(sortfun) + i += 1 + return [i[0] for i in r] def count(self): '''Get the number of nodes in this class. diff --git a/test/db_test_base.py b/test/db_test_base.py index 14a9e38..a69b859 100644 --- a/test/db_test_base.py +++ b/test/db_test_base.py @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: db_test_base.py,v 1.20 2004-03-24 04:57:25 richard Exp $ +# $Id: db_test_base.py,v 1.21 2004-04-05 07:13:10 richard Exp $ import unittest, os, shutil, errno, imp, sys, time, pprint @@ -892,6 +892,11 @@ class DBTest(MyTestCase): # descending should sort 1d, 1:10, None ae(filt(None, {}, ('-','foo'), (None,None)), ['2', '1', '4', '3']) + def testFilteringMultilinkSort(self): + ae, filt = self.filteringSetup() + ae(filt(None, {}, ('+','nosy'), (None,None)), ['1', '2', '4', '3']) + ae(filt(None, {}, ('-','nosy'), (None,None)), ['3', '4', '1', '2']) + # XXX add sorting tests for other types # XXX test auditors and reactors -- 2.30.2