From 33d330cc405e79256eb5cf3a67787c92fba0cb52 Mon Sep 17 00:00:00 2001 From: stephenrauch Date: Tue, 26 May 2015 18:57:45 -0700 Subject: [PATCH] fix belong() with empty set for MongoDB and GAE fix ~ with == and != for MongoDB and GAE --- pydal/adapters/google_adapters.py | 9 ++++++++- pydal/adapters/mongo.py | 17 +++++++++++++---- tests/nosql.py | 3 +++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/pydal/adapters/google_adapters.py b/pydal/adapters/google_adapters.py index 71aef5999..6b4c793af 100644 --- a/pydal/adapters/google_adapters.py +++ b/pydal/adapters/google_adapters.py @@ -311,6 +311,11 @@ def BELONGS(self,first,second=None): raise SyntaxError("Not supported") if not isinstance(second, list): second = list(second) + if len(second) == 0: + # return a filter which will return a null set + f = self.EQ(first,0) + f.filter_all = True + return f return self.gaef(first,'in',second) def CONTAINS(self,first,second,case_sensitive=False): @@ -327,7 +332,7 @@ def NOT(self, first): elif op == self.EQ: r = self.gaef(f, '!=', s) elif op == self.NE: - r = self.gaef(f, '==', s) + r = self.gaef(f, '=', s) elif op == self.LT: r = self.gaef(f, '>=', s) elif op == self.LE: @@ -409,6 +414,8 @@ def select_raw(self,query,fields=None,attributes=None,count_only=False): if filters == None: items = tableobj.query(default_options=qo) + elif hasattr(filters,'filter_all') and filters.filter_all: + items = [] elif (hasattr(filters,'_FilterNode__name') and filters._FilterNode__name=='__key__' and filters._FilterNode__opsymbol=='='): diff --git a/pydal/adapters/mongo.py b/pydal/adapters/mongo.py index 89fe03f9a..104aac7f4 100644 --- a/pydal/adapters/mongo.py +++ b/pydal/adapters/mongo.py @@ -443,6 +443,7 @@ def NOT(self, first): op = self.expand(first) op_k = list(op)[0] op_body = op[op_k] + r = None if type(op_body) is list: # apply De Morgan law for and/or # not(A and B) -> not(A) or not(B) @@ -450,7 +451,14 @@ def NOT(self, first): not_op = '$and' if op_k == '$or' else '$or' r = {not_op: [self.NOT(first.first), self.NOT(first.second)]} else: - r = {op_k: {'$not': op_body}} + try: + sub_ops = list(op_body.keys()) + if len(sub_ops) == 1 and sub_ops[0] == '$ne': + r = {op_k: op_body['$ne']} + except: + r = {op_k: {'$ne': op_body}} + if r == None: + r = {op_k: {'$not': op_body}} return r def AND(self,first,second): @@ -463,9 +471,10 @@ def OR(self,first,second): def BELONGS(self, first, second): if isinstance(second, str): - return {self.expand(first) : {"$in" : [ second[:-1]]} } - elif second==[] or second==() or second==set(): - return {1:0} + # this is broken, the only way second is a string is if it has + # been converted to SQL. This no worky. This might be made to + # work if _select did not return SQL. + raise RuntimeError("nested queries not supported") items = [self.expand(item, first.type) for item in second] return {self.expand(first) : {"$in" : items} } diff --git a/tests/nosql.py b/tests/nosql.py index 766c63b9f..86b14fea3 100644 --- a/tests/nosql.py +++ b/tests/nosql.py @@ -327,6 +327,8 @@ def testRun(self): self.assertEqual(db((db.tt.aa > '1') & (db.tt.aa < '3')).count(), 1) self.assertEqual(db((db.tt.aa > '1') | (db.tt.aa < '3')).count(), 3) # Test not operator + self.assertEqual(db(~(db.tt.aa != '1')).count(), 1) + self.assertEqual(db(~(db.tt.aa == '1')).count(), 2) self.assertEqual(db((db.tt.aa > '1') & ~(db.tt.aa > '2')).count(), 1) self.assertEqual(db(~(db.tt.aa > '1') & (db.tt.aa > '2')).count(), 0) self.assertEqual(db(~((db.tt.aa < '1') | (db.tt.aa > '2'))).count(), 2) @@ -410,6 +412,7 @@ def testRun(self): self.assertEqual(db(db.tt.aa.belongs(['1', '3'])).count(), 2) self.assertEqual(db(db.tt.aa.belongs(['1', '3'])).count(), 2) self.assertEqual(db(db.tt.id.belongs([self.i_id])).count(), 1) + self.assertEqual(db(db.tt.id.belongs([])).count(), 0) @unittest.skipIf(IS_GAE or IS_MONGODB, "Datastore/Mongodb belongs() does not accept nested queries") def testNested(self):