[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).
--- 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"')