Skip to content

Commit a763a13

Browse files
committed
Implement expressions for Link properties
1 parent 7406257 commit a763a13

File tree

2 files changed

+51
-17
lines changed

2 files changed

+51
-17
lines changed

roundup/backends/rdbms_common.py

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2453,6 +2453,53 @@ def _filter_multilink_expression_fallback(self, proptree, expr):
24532453
# we have ids of the classname table
24542454
return ids.where("_%s.id" % classname, self.db.arg)
24552455

2456+
def _filter_link_expression(self, proptree, v):
2457+
""" Filter elements in the table that match the given expression
2458+
"""
2459+
pln = proptree.parent.uniqname
2460+
prp = proptree.name
2461+
try:
2462+
opcodes = [int(x) for x in v]
2463+
if min(opcodes) >= -1:
2464+
raise ValueError()
2465+
expr = compile_expression(opcodes)
2466+
# NULL doesn't compare to NULL in SQL
2467+
# So not (x = '1') will *not* include NULL values for x
2468+
# That's why we need that and clause:
2469+
atom = "_%s._%s = %s and _%s._%s is not NULL" % (
2470+
pln, prp, self.db.arg, pln, prp)
2471+
atom_nil = "_%s._%s is NULL" % (pln, prp)
2472+
lambda_atom = lambda n: atom if n.x >= 0 else atom_nil
2473+
values = []
2474+
w = expr.generate(lambda_atom)
2475+
def collect_values(n):
2476+
if n.x >= 0:
2477+
values.append(n.x)
2478+
expr.visit(collect_values)
2479+
return w, values
2480+
except:
2481+
pass
2482+
# Fallback to original code
2483+
args = []
2484+
where = None
2485+
d = {}
2486+
for entry in v:
2487+
if entry == '-1':
2488+
entry = None
2489+
d[entry] = entry
2490+
l = []
2491+
if None in d or not d:
2492+
if None in d: del d[None]
2493+
l.append('_%s._%s is NULL'%(pln, prp))
2494+
if d:
2495+
v = list(d)
2496+
s = ','.join([self.db.arg for x in v])
2497+
l.append('(_%s._%s in (%s))'%(pln, prp, s))
2498+
args = v
2499+
if l:
2500+
where = '(' + ' or '.join(l) +')'
2501+
return where, args
2502+
24562503
def _filter_multilink_expression(self, proptree, v):
24572504
""" Filters out elements of the classname table that do not
24582505
match the given expression.
@@ -2678,22 +2725,10 @@ def _filter_sql (self, search_matches, filterspec, srt=[], grp=[], retr=0,
26782725
where.append('_%s._%s=_%s.id'%(pln, k, ln))
26792726
if p.has_values:
26802727
if isinstance(v, type([])):
2681-
d = {}
2682-
for entry in v:
2683-
if entry == '-1':
2684-
entry = None
2685-
d[entry] = entry
2686-
l = []
2687-
if None in d or not d:
2688-
if None in d: del d[None]
2689-
l.append('_%s._%s is NULL'%(pln, k))
2690-
if d:
2691-
v = list(d)
2692-
s = ','.join([a for x in v])
2693-
l.append('(_%s._%s in (%s))'%(pln, k, s))
2694-
args = args + v
2695-
if l:
2696-
where.append('(' + ' or '.join(l) +')')
2728+
w, arg = self._filter_link_expression(p, v)
2729+
if w:
2730+
where.append(w)
2731+
args += arg
26972732
else:
26982733
if v in ('-1', None):
26992734
v = None

test/db_test_base.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1859,7 +1859,6 @@ def testFilteringLink(self):
18591859
ae(filt(None, {a: ['-1', None]}, ('+','id'), grp), ['3','4'])
18601860
ae(filt(None, {a: ['1', None]}, ('+','id'), grp), ['1', '3','4'])
18611861

1862-
@pytest.mark.xfail
18631862
def testFilteringLinkExpression(self):
18641863
ae, iiter = self.filteringSetup()
18651864
a = 'assignedto'

0 commit comments

Comments
 (0)