[querier] fix sql generated w/ NOT relation and shared variable: ensure variable's table is in parent select'scope 3.5
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Wed, 16 Sep 2009 14:16:19 +0200
branch3.5
changeset 3238 988a72e59b2b
parent 3237 ee2253f9fbe6
child 3239 1ceac4cd4fb7
[querier] fix sql generated w/ NOT relation and shared variable: ensure variable's table is in parent select'scope
server/sources/rql2sql.py
server/test/unittest_rql2sql.py
--- a/server/sources/rql2sql.py	Tue Sep 15 19:04:09 2009 +0200
+++ b/server/sources/rql2sql.py	Wed Sep 16 14:16:19 2009 +0200
@@ -336,6 +336,7 @@
         self._varmap = varmap
         self._query_attrs = {}
         self._state = None
+        self._not_scope_offset = 0
         try:
             # union query for each rqlst / solution
             sql = self.union_sql(union)
@@ -553,7 +554,11 @@
 
     def visit_not(self, node):
         self._state.push_scope()
+        if isinstance(node.children[0], Relation):
+            self._not_scope_offset += 1
         csql = node.children[0].accept(self)
+        if isinstance(node.children[0], Relation):
+            self._not_scope_offset -= 1
         sqls, tables = self._state.pop_scope()
         if node in self._state.done or not csql:
             # already processed or no sql generated by children
@@ -1080,12 +1085,16 @@
         # a EXISTS node
         if var.sqlscope is var.stmt:
             scope = 0
+        # don't consider not_scope_offset if the variable is only used in one
+        # relation
+        elif len(var.stinfo['relations']) > 1:
+            scope = -1 - self._not_scope_offset
         else:
             scope = -1
         try:
             sql = self._varmap[var.name]
             table = sql.split('.', 1)[0]
-            if scope == -1:
+            if scope < 0:
                 scope = self._varmap_table_scope(var.stmt, table)
             self.add_table(table, scope=scope)
         except KeyError:
@@ -1146,8 +1155,8 @@
             key = table
         if key in self._state.tables:
             return
-        if scope == -1:
-            scope = len(self._state.actual_tables) - 1
+        if scope < 0:
+            scope = len(self._state.actual_tables) + scope
         self._state.tables[key] = (scope, table)
         self._state.actual_tables[scope].append(table)
 
--- a/server/test/unittest_rql2sql.py	Tue Sep 15 19:04:09 2009 +0200
+++ b/server/test/unittest_rql2sql.py	Wed Sep 16 14:16:19 2009 +0200
@@ -642,6 +642,13 @@
 WHERE X.cw_in_state=S.cw_eid
 ORDER BY 2) AS T1'''),
 
+    ('Any O,AA,AB,AC ORDERBY AC DESC '
+     'WHERE NOT S use_email O, S eid 1, O is EmailAddress, O address AA, O alias AB, O modification_date AC, '
+     'EXISTS(A use_email O, EXISTS(A identity B, NOT B in_group D, D name "guests", D is CWGroup), A is CWUser), B eid 2',
+     '''SELECT O.cw_eid, O.cw_address, O.cw_alias, O.cw_modification_date
+FROM cw_EmailAddress AS O
+WHERE NOT EXISTS(SELECT 1 FROM use_email_relation AS rel_use_email0 WHERE rel_use_email0.eid_from=1 AND rel_use_email0.eid_to=O.cw_eid) AND EXISTS(SELECT 1 FROM use_email_relation AS rel_use_email1 WHERE rel_use_email1.eid_to=O.cw_eid AND EXISTS(SELECT 1 FROM cw_CWGroup AS D WHERE rel_use_email1.eid_from=2 AND NOT EXISTS(SELECT 1 FROM in_group_relation AS rel_in_group2 WHERE rel_in_group2.eid_from=2 AND rel_in_group2.eid_to=D.cw_eid) AND D.cw_name=guests))
+ORDER BY 4 DESC'''),
     ]
 
 MULTIPLE_SEL = [