changeset 6151:ff059afae50a

Make 'find' work for rev_multilink properties
author Ralf Schlatterbeck <rsc@runtux.com>
date Fri, 01 May 2020 16:34:35 +0200
parents edbd4bba728a
children 546763f4ce44
files roundup/backends/back_anydbm.py roundup/backends/rdbms_common.py test/db_test_base.py
diffstat 3 files changed, 53 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/roundup/backends/back_anydbm.py	Fri May 01 16:33:05 2020 +0200
+++ b/roundup/backends/back_anydbm.py	Fri May 01 16:34:35 2020 +0200
@@ -1581,6 +1581,7 @@
         # ok, now do the find
         cldb = self.db.getclassdb(self.classname)
         l = []
+        rev_multilinks = []
         try:
             for id in self.getnodeids(db=cldb):
                 item = self.db.getnode(self.classname, id, db=cldb)
@@ -1607,6 +1608,9 @@
                         l.append(id)
                         break
                     elif isinstance(prop, hyperdb.Multilink):
+                        if prop.rev_property:
+                            rev_multilinks.append ((prop, itemids))
+                            continue
                         hit = 0
                         for v in value:
                             if v in itemids:
@@ -1615,6 +1619,15 @@
                                 break
                         if hit:
                             break
+            for prop, itemids in rev_multilinks:
+                rprop = prop.rev_property
+                fun = l.append
+                if isinstance (rprop, hyperdb.Multilink):
+                    fun = l.extend
+                for id in itemids:
+                    fun(rprop.cls.get(id, rprop.name))
+            if rev_multilinks:
+                l = list(sorted(set(l)))
         finally:
             cldb.close()
         return l
--- a/roundup/backends/rdbms_common.py	Fri May 01 16:33:05 2020 +0200
+++ b/roundup/backends/rdbms_common.py	Fri May 01 16:34:35 2020 +0200
@@ -2252,21 +2252,29 @@
 
         # now multilinks
         for prop, values in propspec.items():
-            if not isinstance(props[prop], hyperdb.Multilink):
+            p = props[prop]
+            if not isinstance(p, hyperdb.Multilink):
                 continue
             if not values:
                 continue
             allvalues += (0, )
+            tn = p.table_name
+            ln = p.linkid_name
+            nn = p.nodeid_name
+            cn = '_' + self.classname
+            ret = ''
+            if p.rev_property and isinstance(p.rev_property, Link):
+                ret = 'and %s.__retired__=%s ' % (tn, a)
+                allvalues += (0, )
             if type(values) is type(''):
                 allvalues += (values,)
                 s = a
             else:
                 allvalues += tuple(values)
                 s = ','.join([a]*len(values))
-            tn = '%s_%s'%(self.classname, prop)
-            sql.append("""select id from _%s, %s where  __retired__=%s
-                  and id = %s.nodeid and %s.linkid in (%s)"""%(self.classname,
-                  tn, a, tn, tn, s))
+            sql.append("""select %s.id from %s, %s where  %s.__retired__=%s
+                  %sand %s.id = %s.%s and %s.%s in (%s)"""%(cn, cn, tn, cn,
+                  a, ret, cn, tn, nn, tn, ln, s))
 
         if not sql:
             return []
--- a/test/db_test_base.py	Fri May 01 16:33:05 2020 +0200
+++ b/test/db_test_base.py	Fri May 01 16:34:35 2020 +0200
@@ -1564,6 +1564,33 @@
         got.sort()
         self.assertEqual(got, [one, three])
 
+    def testFindRevLinkMultilink(self):
+        ae, filter, filter_iter = self.filteringSetupTransitiveSearch('user')
+        ni = 'nosy_issues'
+        self.db.issue.set('6', nosy=['3', '4', '5'])
+        self.db.issue.set('7', nosy=['5'])
+        # After this setup we have the following values for nosy:
+        # issue  assignedto  nosy
+        # 1:      6          4
+        # 2:      6          5
+        # 3:      7
+        # 4:      8
+        # 5:      9
+        # 6:      10         3, 4, 5
+        # 7:      10         5
+        # 8:      10
+        # assignedto links back from 'issues'
+        # nosy links back from 'nosy_issues'
+        self.assertEqual(self.db.user.find(issues={'1':1}), ['6'])
+        self.assertEqual(self.db.user.find(issues={'8':1}), ['10'])
+        self.assertEqual(self.db.user.find(issues={'2':1, '5':1}), ['6', '9'])
+        self.assertEqual(self.db.user.find(nosy_issues={'8':1}), [])
+        self.assertEqual(self.db.user.find(nosy_issues={'6':1}),
+            ['3', '4', '5'])
+        self.assertEqual(self.db.user.find(nosy_issues={'3':1, '5':1}), [])
+        self.assertEqual(self.db.user.find(nosy_issues={'2':1, '6':1, '7':1}),
+            ['3', '4', '5'])
+
     def testFindLinkFail(self):
         self._find_test_setup()
         self.assertEqual(self.db.issue.find(status='4'), [])

Roundup Issue Tracker: http://roundup-tracker.org/