[rql rewrite] may_be_shared_with should consider relation's scope (closes #3024730) stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Mon, 22 Jul 2013 11:09:28 +0200
branchstable
changeset 9170 e6fe77dbcfdf
parent 9169 544b22a3485b
child 9171 be9596750678
[rql rewrite] may_be_shared_with should consider relation's scope (closes #3024730) When a relation's scope is not the current statement, it must not be shared (instead of comparing the statement).
rqlrewrite.py
test/unittest_rqlrewrite.py
--- a/rqlrewrite.py	Thu Jul 18 10:19:06 2013 +0200
+++ b/rqlrewrite.py	Mon Jul 22 11:09:28 2013 +0200
@@ -673,9 +673,9 @@
             except KeyError:
                 # may be raised by vi['xhs_rels'][sniprel.r_type]
                 continue
-            # don't share if relation's statement is not the current statement
-            if orel.stmt is not stmt:
-                return None
+            # don't share if relation's scope is not the current statement
+            if orel.scope is not stmt:
+                continue
             # can't share neged relation or relations with different outer join
             if (orel.neged(strict=True) or sniprel.neged(strict=True)
                 or (orel.optional and orel.optional != sniprel.optional)):
--- a/test/unittest_rqlrewrite.py	Thu Jul 18 10:19:06 2013 +0200
+++ b/test/unittest_rqlrewrite.py	Mon Jul 22 11:09:28 2013 +0200
@@ -331,6 +331,21 @@
                          "EXISTS(A subworkflow_exit EXIT, A name 'hop', A is WorkflowTransition), "
                          "C is WorkflowTransition")
 
+    def test_relation_non_optimization_2(self):
+        """See #3024730"""
+        # 'X inlined_note N' must not be shared with 'C inlined_note N'
+        # previously inserted, else this may introduce duplicated results, as N
+        # will then be shared by multiple EXISTS and so at SQL generation time,
+        # the table will be in the FROM clause of the outermost query
+        rqlst = parse('Any A,C WHERE A inlined_card C')
+        rewrite(rqlst, {('A', 'X'): ('X inlined_card C, C inlined_note N, N owned_by U',),
+                        ('C', 'X'): ('X inlined_note N, N owned_by U',)}, {})
+        self.assertEqual(rqlst.as_string(),
+                         'Any A,C WHERE A inlined_card C, D eid %(E)s, '
+                         'EXISTS(C inlined_note B, B owned_by D, B is Note), '
+                         'EXISTS(C inlined_note F, F owned_by D, F is Note), '
+                         'A is Affaire, C is Card')
+
     def test_unsupported_constraint_1(self):
         # CWUser doesn't have require_permission
         trinfo_constraint = ('X wf_info_for Y, Y require_permission P, P name "read"')