Mercurial > p > roundup > code
changeset 6415:dbacf6bf2a2f
Implement expressions for Link properties
| author | Ralf Schlatterbeck <rsc@runtux.com> |
|---|---|
| date | Tue, 18 May 2021 08:50:46 +0200 |
| parents | 3dbf1bc5e567 |
| children | 99d344aa825d |
| files | roundup/backends/rdbms_common.py test/db_test_base.py |
| diffstat | 2 files changed, 51 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/roundup/backends/rdbms_common.py Mon May 17 15:25:17 2021 -0400 +++ b/roundup/backends/rdbms_common.py Tue May 18 08:50:46 2021 +0200 @@ -2453,6 +2453,53 @@ # we have ids of the classname table return ids.where("_%s.id" % classname, self.db.arg) + def _filter_link_expression(self, proptree, v): + """ Filter elements in the table that match the given expression + """ + pln = proptree.parent.uniqname + prp = proptree.name + try: + opcodes = [int(x) for x in v] + if min(opcodes) >= -1: + raise ValueError() + expr = compile_expression(opcodes) + # NULL doesn't compare to NULL in SQL + # So not (x = '1') will *not* include NULL values for x + # That's why we need that and clause: + atom = "_%s._%s = %s and _%s._%s is not NULL" % ( + pln, prp, self.db.arg, pln, prp) + atom_nil = "_%s._%s is NULL" % (pln, prp) + lambda_atom = lambda n: atom if n.x >= 0 else atom_nil + values = [] + w = expr.generate(lambda_atom) + def collect_values(n): + if n.x >= 0: + values.append(n.x) + expr.visit(collect_values) + return w, values + except: + pass + # Fallback to original code + args = [] + where = None + d = {} + for entry in v: + if entry == '-1': + entry = None + d[entry] = entry + l = [] + if None in d or not d: + if None in d: del d[None] + l.append('_%s._%s is NULL'%(pln, prp)) + if d: + v = list(d) + s = ','.join([self.db.arg for x in v]) + l.append('(_%s._%s in (%s))'%(pln, prp, s)) + args = v + if l: + where = '(' + ' or '.join(l) +')' + return where, args + def _filter_multilink_expression(self, proptree, v): """ Filters out elements of the classname table that do not match the given expression. @@ -2678,22 +2725,10 @@ where.append('_%s._%s=_%s.id'%(pln, k, ln)) if p.has_values: if isinstance(v, type([])): - d = {} - for entry in v: - if entry == '-1': - entry = None - d[entry] = entry - l = [] - if None in d or not d: - if None in d: del d[None] - l.append('_%s._%s is NULL'%(pln, k)) - if d: - v = list(d) - s = ','.join([a for x in v]) - l.append('(_%s._%s in (%s))'%(pln, k, s)) - args = args + v - if l: - where.append('(' + ' or '.join(l) +')') + w, arg = self._filter_link_expression(p, v) + if w: + where.append(w) + args += arg else: if v in ('-1', None): v = None
--- a/test/db_test_base.py Mon May 17 15:25:17 2021 -0400 +++ b/test/db_test_base.py Tue May 18 08:50:46 2021 +0200 @@ -1859,7 +1859,6 @@ ae(filt(None, {a: ['-1', None]}, ('+','id'), grp), ['3','4']) ae(filt(None, {a: ['1', None]}, ('+','id'), grp), ['1', '3','4']) - @pytest.mark.xfail def testFilteringLinkExpression(self): ae, iiter = self.filteringSetup() a = 'assignedto'
