Skip to content

Commit eb05658

Browse files
author
Ralf Schlatterbeck
committed
Of course for Links there is the same bug as I fixed before for multilinks.
But it turns out that searching for None is valid for a link. So we can't use None as a guard in support.Proptree, I introduced the has_values flag there and use it in the sql search too.
1 parent 1346187 commit eb05658

File tree

3 files changed

+41
-34
lines changed

3 files changed

+41
-34
lines changed

roundup/backends/rdbms_common.py

Lines changed: 31 additions & 30 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: rdbms_common.py,v 1.173 2006-07-13 10:14:56 schlatterbeck Exp $
18+
#$Id: rdbms_common.py,v 1.174 2006-07-13 13:30:39 schlatterbeck Exp $
1919
''' Relational database (SQL) backend common code.
2020
2121
Basics:
@@ -2069,11 +2069,8 @@ def filter(self, search_matches, filterspec, sort=(None,None),
20692069
k = p.name
20702070
v = p.val
20712071
propclass = p.prcls
2072-
if p.children and not isinstance(propclass, Multilink):
2073-
if not isinstance(propclass, Link):
2074-
raise ValueError,"%s must be Link/Multilink property"%k
2075-
frum.append('_%s as _%s' % (cn, ln))
2076-
where.append('_%s._%s=_%s.id'%(pln, k, ln))
2072+
if p.children and not isinstance(propclass, (Link, Multilink)):
2073+
raise ValueError,"%s must be Link/Multilink property"%k
20772074
# now do other where clause stuff
20782075
elif isinstance(propclass, Multilink):
20792076
mlfilt = 1
@@ -2088,7 +2085,7 @@ def filter(self, search_matches, filterspec, sort=(None,None),
20882085
if p.children:
20892086
frum.append('_%s as _%s' % (cn, ln))
20902087
where.append('%s.linkid=_%s.id'%(tn, ln))
2091-
if v:
2088+
if p.has_values:
20922089
if isinstance(v, type([])):
20932090
s = ','.join([a for x in v])
20942091
where.append('%s.linkid in (%s)'%(tn, s))
@@ -2119,30 +2116,34 @@ def filter(self, search_matches, filterspec, sort=(None,None),
21192116
+')')
21202117
# note: args are embedded in the query string now
21212118
elif isinstance(propclass, Link):
2122-
if isinstance(v, type([])):
2123-
d = {}
2124-
for entry in v:
2125-
if entry == '-1':
2126-
entry = None
2127-
d[entry] = entry
2128-
l = []
2129-
if d.has_key(None) or not d:
2130-
del d[None]
2131-
l.append('_%s._%s is NULL'%(pln, k))
2132-
if d:
2133-
v = d.keys()
2134-
s = ','.join([a for x in v])
2135-
l.append('(_%s._%s in (%s))'%(pln, k, s))
2136-
args = args + v
2137-
if l:
2138-
where.append('(' + ' or '.join(l) +')')
2139-
else:
2140-
if v in ('-1', None):
2141-
v = None
2142-
where.append('_%s._%s is NULL'%(pln, k))
2119+
if p.children:
2120+
frum.append('_%s as _%s' % (cn, ln))
2121+
where.append('_%s._%s=_%s.id'%(pln, k, ln))
2122+
if p.has_values:
2123+
if isinstance(v, type([])):
2124+
d = {}
2125+
for entry in v:
2126+
if entry == '-1':
2127+
entry = None
2128+
d[entry] = entry
2129+
l = []
2130+
if d.has_key(None) or not d:
2131+
del d[None]
2132+
l.append('_%s._%s is NULL'%(pln, k))
2133+
if d:
2134+
v = d.keys()
2135+
s = ','.join([a for x in v])
2136+
l.append('(_%s._%s in (%s))'%(pln, k, s))
2137+
args = args + v
2138+
if l:
2139+
where.append('(' + ' or '.join(l) +')')
21432140
else:
2144-
where.append('_%s._%s=%s'%(pln, k, a))
2145-
args.append(v)
2141+
if v in ('-1', None):
2142+
v = None
2143+
where.append('_%s._%s is NULL'%(pln, k))
2144+
else:
2145+
where.append('_%s._%s=%s'%(pln, k, a))
2146+
args.append(v)
21462147
elif isinstance(propclass, Date):
21472148
dc = self.db.hyperdb_to_sql_value[hyperdb.Date]
21482149
if isinstance(v, type([])):

roundup/support.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,13 @@ class Proptree(object):
125125
''' Simple tree data structure for optimizing searching of properties
126126
'''
127127

128-
def __init__(self, db, cls, name, props, parent = None, val = None):
128+
def __init__(self, db, cls, name, props, parent = None):
129129
self.db = db
130130
self.name = name
131131
self.props = props
132132
self.parent = parent
133-
self._val = val
133+
self._val = None
134+
self.has_values = False
134135
self.cls = cls
135136
self.classname = None
136137
self.uniqname = None
@@ -171,7 +172,7 @@ def _set_val(self, val):
171172
"""Check if self._val is already defined. If yes, we compute the
172173
intersection of the old and the new value(s)
173174
"""
174-
if self._val:
175+
if self.has_values:
175176
v = self._val
176177
if not isinstance(self._val, type([])):
177178
v = [self._val]
@@ -180,6 +181,7 @@ def _set_val(self, val):
180181
self._val = [v for v in vals]
181182
else:
182183
self._val = val
184+
self.has_values = True
183185

184186
val = property(lambda self: self._val, _set_val)
185187

test/db_test_base.py

Lines changed: 5 additions & 1 deletion
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.71 2006-07-13 10:14:56 schlatterbeck Exp $
18+
# $Id: db_test_base.py,v 1.72 2006-07-13 13:30:39 schlatterbeck Exp $
1919

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

@@ -977,6 +977,8 @@ def testFilteringLink(self):
977977
ae(filt(None, {'status': '1'}, ('+','id'), (None,None)), ['2','3'])
978978
ae(filt(None, {'assignedto': '-1'}, ('+','id'), (None,None)), ['3','4'])
979979
ae(filt(None, {'assignedto': None}, ('+','id'), (None,None)), ['3','4'])
980+
ae(filt(None, {'assignedto': [None]}, ('+','id'), (None,None)),
981+
['3','4'])
980982
ae(filt(None, {'assignedto': ['-1', None]}, ('+','id'), (None,None)),
981983
['3','4'])
982984
ae(filt(None, {'assignedto': ['1', None]}, ('+','id'), (None,None)),
@@ -1148,6 +1150,8 @@ def testFilteringTransitiveLinkUser(self):
11481150
ae(ufilt(None, {'supervisor.username': 'grouplead2',
11491151
'supervisor.supervisor.username': 'ceo'}, ('+','username')),
11501152
['8', '9', '10'])
1153+
ae(ufilt(None, {'supervisor.supervisor': '3', 'supervisor': '4'},
1154+
('+','username')), ['6', '7'])
11511155

11521156
def testFilteringTransitiveLinkIssue(self):
11531157
ae, filt = self.filteringSetupTransitiveSearch()

0 commit comments

Comments
 (0)