Code

implemented ability to search for multilink properties with no value (not in mk)
authorrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Wed, 26 Mar 2003 04:56:21 +0000 (04:56 +0000)
committerrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Wed, 26 Mar 2003 04:56:21 +0000 (04:56 +0000)
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@1627 57a73879-2fb5-44c3-a270-3262357dd7e2

CHANGES.txt
roundup/backends/back_anydbm.py
roundup/backends/rdbms_common.py
test/test_db.py

index e15788b0074aa295436fdd7322ce34bb8b2af8b8..bd18ae10f00be50a77692ed8db68a8d3bc513464 100644 (file)
@@ -52,6 +52,7 @@ Feature:
 - added ability to restore retired nodes
 - more lenient date input and addition Interval input support (sf bug 677764)
 - roundup mailgw now handles apop
+- implemented ability to search for multilink properties with no value
 
 
 Fixed:
@@ -71,8 +72,6 @@ Fixed:
 - fixed export/import of retired nodes (sf bug 685273)
 - remember the display template specified during edit (sf bug 701815)
 - added example HTML tempating for vacation flag (sf bug 701722)
-- only look for CSV files when importing (thanks Dan Grassi)
-- can now unset values in CSV editing (sf bug 704788)
 - finally, tables autosize columns (sf bug 609070)
 - added creation to index columns (sf bug 708247)
 
@@ -82,6 +81,8 @@ Fixed:
 - fixed sqlite rollback/caching bug (sf bug 689383)
 - fixed rdbms table update detection logic (sf bug 703297)
 - fixed detection of bad date specs (sf bug 691439)
+- only look for CSV files when importing (thanks Dan Grassi)
+- can now unset values in CSV editing (sf bug 704788)
 - fixed rdbms email address lookup (case insensitivity)
 
 
index c167c3cdd501a31fb5623b03ef5c6e619a47e9e7..b4124439ace17d12eb955e8d4edf3535a4e4a941 100644 (file)
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-#$Id: back_anydbm.py,v 1.113 2003-03-17 22:03:04 kedder Exp $
+#$Id: back_anydbm.py,v 1.114 2003-03-26 04:56:21 richard Exp $
 '''
 This module defines a backend that saves the hyperdatabase in a database
 chosen by anydbm. It is guaranteed to always be available in python
@@ -1601,7 +1601,9 @@ class Class(hyperdb.Class):
 
             The filter must match all properties specificed - but if the
             property value to match is a list, any one of the values in the
-            list may match for that property to match.
+            list may match for that property to match. Unless the property
+            is a Multilink, in which case the item's property list must
+            match the filterspec list.
         '''
         cn = self.classname
 
@@ -1624,7 +1626,9 @@ class Class(hyperdb.Class):
                 u = []
                 link_class =  self.db.classes[propclass.classname]
                 for entry in v:
-                    if entry == '-1': entry = None
+                    # the value -1 is a special "not set" sentinel
+                    if entry == '-1':
+                        entry = None
                     elif not num_re.match(entry):
                         try:
                             entry = link_class.lookup(entry)
@@ -1635,8 +1639,12 @@ class Class(hyperdb.Class):
 
                 l.append((LINK, k, u))
             elif isinstance(propclass, Multilink):
-                if type(v) is not type([]):
+                # the value -1 is a special "not set" sentinel
+                if v == '-1':
+                    v = []
+                elif type(v) is not type([]):
                     v = [v]
+
                 # replace key values with node ids
                 u = []
                 link_class =  self.db.classes[propclass.classname]
@@ -1648,6 +1656,7 @@ class Class(hyperdb.Class):
                             raise ValueError, 'new property "%s": %s not a %s'%(
                                 k, entry, self.properties[k].classname)
                     u.append(entry)
+                u.sort()
                 l.append((MULTILINK, k, u))
             elif isinstance(propclass, String) and k != 'id':
                 # simple glob searching
@@ -1710,6 +1719,12 @@ class Class(hyperdb.Class):
                         # filterspec aren't in this node's property, then skip
                         # it
                         have = node[k]
+                        # check for matching the absence of multilink values
+                        if not v and have:
+                            break
+
+                        # othewise, make sure this node has each of the
+                        # required values
                         for want in v:
                             if want not in have:
                                 break
index a350425677f7d6218cc6c68eeded25043b4375d5..c627b629b962c61ec71bebc4ff4aa177acddf3d8 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: rdbms_common.py,v 1.48 2003-03-24 04:47:44 richard Exp $
+# $Id: rdbms_common.py,v 1.49 2003-03-26 04:56:21 richard Exp $
 ''' Relational database (SQL) backend common code.
 
 Basics:
@@ -1786,13 +1786,18 @@ class Class(hyperdb.Class):
             # now do other where clause stuff
             if isinstance(propclass, Multilink):
                 tn = '%s_%s'%(cn, k)
-                frum.append(tn)
                 if isinstance(v, type([])):
+                    frum.append(tn)
                     s = ','.join([a for x in v])
                     where.append('id=%s.nodeid and %s.linkid in (%s)'%(tn,tn,s))
                     args = args + v
+                elif v == '-1':
+                    # only match rows that have count(linkid)=0 in the
+                    # corresponding multilink table)
+                    where.append('id not in (select nodeid from %s)'%tn)
                 else:
-                    where.append('id=%s.nodeid and %s.linkid = %s'%(tn, tn, a))
+                    frum.append(tn)
+                    where.append('id=%s.nodeid and %s.linkid=%s'%(tn, tn, a))
                     args.append(v)
             elif k == 'id':
                 if isinstance(v, type([])):
index 742e65bb0868e541bbdc0d05eab13d720cd80d5f..b631cbeebee51cb9d82bcf716befe2af59bd959d 100644 (file)
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: test_db.py,v 1.81 2003-03-22 22:43:21 richard Exp $ 
+# $Id: test_db.py,v 1.82 2003-03-26 04:56:21 richard Exp $ 
 
 import unittest, os, shutil, time
 
@@ -672,6 +672,7 @@ class anydbmDBTestCase(MyTestCase):
     def testFilteringMultilink(self):
         ae, filt = self.filteringSetup()
         ae(filt(None, {'nosy': '2'}, ('+','id'), (None,None)), ['3'])
+        ae(filt(None, {'nosy': '-1'}, ('+','id'), (None,None)), ['1', '2'])
 
     def testFilteringMany(self):
         ae, filt = self.filteringSetup()