@@ -93,7 +93,7 @@ def setupTracker(dirname, backend="anydbm", optimize=False):
9393def setupSchema (db , create , module ):
9494 mls = module .Class (db , "mls" , name = String ())
9595 mls .setkey ("name" )
96- keyword = module .Class (db , "keyword" , name = String ())
96+ keyword = module .Class (db , "keyword" , name = String (), order = Number () )
9797 keyword .setkey ("name" )
9898 status = module .Class (db , "status" , name = String (), mls = Multilink ("mls" ))
9999 status .setkey ("name" )
@@ -118,7 +118,7 @@ def setupSchema(db, create, module):
118118 files = Multilink ("file" ), assignedto = Link ('user' , quiet = True ,
119119 rev_multilink = 'issues' ), priority = Link ('priority' ),
120120 spam = Multilink ('msg' ), feedback = Link ('msg' ),
121- keywords = Multilink ('keyword' ))
121+ keywords = Multilink ('keyword' ), keywords2 = Multilink ( 'keyword' ) )
122122 stuff = module .Class (db , "stuff" , stuff = String ())
123123 session = module .Class (db , 'session' , title = String ())
124124 msg = module .FileClass (db , "msg" , date = Date (),
@@ -1542,8 +1542,8 @@ def testIndexingPropertiesOnImport(self):
15421542 # import an issue
15431543 title = 'Bzzt'
15441544 nodeid = self .db .issue .import_list (['title' , 'messages' , 'files' ,
1545- 'spam' , 'nosy' , 'superseder' , 'keywords' ], [ repr ( title ), '[]' ,
1546- '[]' , '[]' , '[]' , '[]' , '[]' ])
1545+ 'spam' , 'nosy' , 'superseder' , 'keywords' , 'keywords2' ] ,
1546+ [ repr ( title ), '[]' , '[]' , '[]' , '[]' , '[]' , '[]' , '[]' ])
15471547 self .db .commit ()
15481548
15491549 # Content of title attribute is indexed
@@ -2060,6 +2060,37 @@ def testFilteringMultilinkExpression(self):
20602060 ae (filt (None , {kw : ['4' , '-1' , '-3' , '3' , '-1' , '-4' , '-4' ]}),
20612061 ['1' , '2' , '3' ])
20622062
2063+ def testFilteringTwoMultilinksExpression (self ):
2064+ ae , iiter = self .filteringSetup ()
2065+ kw1 = self .db .keyword .create (name = 'Key1' , order = 10 )
2066+ kw2 = self .db .keyword .create (name = 'Key2' , order = 20 )
2067+ kw3 = self .db .keyword .create (name = 'Key3' , order = 30 )
2068+ kw4 = self .db .keyword .create (name = 'Key4' , order = 40 )
2069+ self .db .issue .set ('1' , keywords = [kw1 , kw2 ])
2070+ self .db .issue .set ('2' , keywords = [kw1 , kw3 ])
2071+ self .db .issue .set ('3' , keywords = [kw2 , kw3 , kw4 ])
2072+ self .db .issue .set ('4' , keywords = [])
2073+ self .db .issue .set ('1' , keywords2 = [kw3 , kw4 ])
2074+ self .db .issue .set ('2' , keywords2 = [kw2 , kw3 ])
2075+ self .db .issue .set ('3' , keywords2 = [kw1 , kw3 , kw4 ])
2076+ self .db .issue .set ('4' , keywords2 = [])
2077+ self .db .commit ()
2078+ kw = 'keywords'
2079+ kw2 = 'keywords2'
2080+ for filt in iiter ():
2081+ # kw: '1' and '3' kw2: '2' and '3'
2082+ ae (filt (None , {kw : ['1' , '3' , '-3' ], kw2 : ['2' , '3' , '-3' ]}), ['2' ])
2083+ # kw: empty kw2: empty
2084+ ae (filt (None , {kw : ['-1' ], kw2 : ['-1' ]}), ['4' ])
2085+ # kw: empty kw2: empty
2086+ ae (filt (None , {kw : [], kw2 : []}), ['4' ])
2087+ # look for both keyword name and order
2088+ ae (filt (None , {'keywords.name' : 'y4' , 'keywords.order' : 40 }), ['3' ])
2089+ # look for both keyword and order non-matching
2090+ ae (filt (None , {kw : '3' , 'keywords.order' : 40 }), [])
2091+ # look for both keyword and order non-matching with kw and kw2
2092+ ae (filt (None , {kw : '3' , 'keywords2.order' : 40 }), ['3' ])
2093+
20632094 def testFilteringRevMultilink (self ):
20642095 ae , iiter = self .filteringSetupTransitiveSearch ('user' )
20652096 ni = 'nosy_issues'
@@ -2102,6 +2133,35 @@ def ls(x):
21022133 self .assertEqual (ls (self .db .user .get ('4' , ni )), ['1' ])
21032134 self .assertEqual (ls (self .db .user .get ('5' , ni )), ['7' ])
21042135
2136+ def testFilteringRevMultilinkQ2 (self ):
2137+ ae , iiter = self .filteringSetupTransitiveSearch ('user' )
2138+ ni = 'nosy_issues'
2139+ nis = 'nosy_issues.status'
2140+ self .db .issue .set ('6' , nosy = ['3' , '4' , '5' ])
2141+ self .db .issue .set ('7' , nosy = ['5' ])
2142+ self .db .commit ()
2143+ # After this setup we have the following values for nosy:
2144+ # The issues '1', '3', '5', '7' have status '2'
2145+ # issue nosy
2146+ # 1: 4
2147+ # 2: 5
2148+ # 3:
2149+ # 4:
2150+ # 5:
2151+ # 6: 3, 4, 5
2152+ # 7: 5
2153+ # 8:
2154+ for filt in iiter ():
2155+ # status of issue is '2'
2156+ ae (filt (None , {nis : ['2' ]}),
2157+ ['4' , '5' ])
2158+ # Issue non-empty and status of issue is '2'
2159+ ae (filt (None , {nis : ['2' ], ni :['-1' , '-2' ]}),
2160+ ['4' , '5' ])
2161+ # empty and status '2'
2162+ # This is the test-case for issue2551119
2163+ ae (filt (None , {nis : ['2' ], ni :['-1' ]}), [])
2164+
21052165 def testFilteringRevMultilinkExpression (self ):
21062166 ae , iiter = self .filteringSetupTransitiveSearch ('user' )
21072167 ni = 'nosy_issues'
@@ -2911,6 +2971,7 @@ def stdoutwrite(s):
29112971 'feedback: <roundup.hyperdb.Link to "msg">\n ' ,
29122972 'files: <roundup.hyperdb.Multilink to "file">\n ' ,
29132973 'foo: <roundup.hyperdb.Interval>\n ' ,
2974+ 'keywords2: <roundup.hyperdb.Multilink to "keyword">\n ' ,
29142975 'keywords: <roundup.hyperdb.Multilink to "keyword">\n ' ,
29152976 'messages: <roundup.hyperdb.Multilink to "msg">\n ' ,
29162977 'nosy: <roundup.hyperdb.Multilink to "user">\n ' ,
@@ -3018,8 +3079,8 @@ def testAddProperty(self):
30183079 keys = sorted (props .keys ())
30193080 self .assertEqual (keys , ['activity' , 'actor' , 'assignedto' , 'creation' ,
30203081 'creator' , 'deadline' , 'feedback' , 'files' , 'fixer' , 'foo' ,
3021- 'id' , 'keywords' , 'messages ' , 'nosy ' , 'priority ' , 'spam ' ,
3022- 'status' , 'superseder' , 'title' ])
3082+ 'id' , 'keywords' , 'keywords2 ' , 'messages ' , 'nosy ' , 'priority ' ,
3083+ 'spam' , ' status' , 'superseder' , 'title' ])
30233084 self .assertEqual (self .db .issue .get ('1' , "fixer" ), None )
30243085
30253086 def testRemoveProperty (self ):
@@ -3032,8 +3093,8 @@ def testRemoveProperty(self):
30323093 keys = sorted (props .keys ())
30333094 self .assertEqual (keys , ['activity' , 'actor' , 'assignedto' , 'creation' ,
30343095 'creator' , 'deadline' , 'feedback' , 'files' , 'foo' , 'id' ,
3035- 'keywords' , 'messages ' , 'nosy ' , 'priority ' , 'spam ' , 'status ' ,
3036- 'superseder' ])
3096+ 'keywords' , 'keywords2 ' , 'messages ' , 'nosy ' , 'priority ' , 'spam ' ,
3097+ 'status' , ' superseder' ])
30373098 self .assertEqual (self .db .issue .list (), ['1' ])
30383099
30393100 def testAddRemoveProperty (self ):
@@ -3047,8 +3108,8 @@ def testAddRemoveProperty(self):
30473108 keys = sorted (props .keys ())
30483109 self .assertEqual (keys , ['activity' , 'actor' , 'assignedto' , 'creation' ,
30493110 'creator' , 'deadline' , 'feedback' , 'files' , 'fixer' , 'foo' , 'id' ,
3050- 'keywords' , 'messages ' , 'nosy ' , 'priority ' , 'spam ' , 'status ' ,
3051- 'superseder' ])
3111+ 'keywords' , 'keywords2 ' , 'messages ' , 'nosy ' , 'priority ' , 'spam ' ,
3112+ 'status' , ' superseder' ])
30523113 self .assertEqual (self .db .issue .list (), ['1' ])
30533114
30543115 def testNosyMail (self ) :
0 commit comments