[ms planning] raise BadRQLQuery when two variables related by a non-crossable relation should come from two different sources (closes #1973767)
--- a/server/msplanner.py Thu Sep 29 12:55:28 2011 +0200
+++ b/server/msplanner.py Thu Sep 29 13:53:34 2011 +0200
@@ -291,6 +291,8 @@
self.sourcesterms = self._sourcesterms = {}
# source : {relation: set(child variable and constant)}
self._crossrelations = {}
+ # term : set(sources)
+ self._discarded_sources = {}
# dictionary of variables and constants which are linked to each other
# using a non final relation supported by multiple sources (crossed or
# not).
@@ -539,6 +541,7 @@
if invariant and source is self.system_source:
continue
self._remove_source_term(source, lhs)
+ self._discarded_sources.setdefault(lhs, set()).add(source)
usesys = self.system_source not in sources
else:
for source, terms in sourcesterms.items():
@@ -546,6 +549,7 @@
if invariant and source is self.system_source:
continue
self._remove_source_term(source, lhs)
+ self._discarded_sources.setdefault(lhs, set()).add(source)
usesys = self.system_source in sources
if rel is None or (len(var.stinfo['relations']) == 2 and
not var.stinfo['selected']):
@@ -697,6 +701,12 @@
rel in self._crossrelations[s]))
if invalid_sources:
self._remove_sources(term, invalid_sources)
+ discarded = self._discarded_sources.get(term)
+ if discarded is not None and not any(x[0] for x in (termsources-invalid_sources)
+ if not x[0] in discarded):
+ raise BadRQLQuery('relation %s cant be crossed but %s and %s should '
+ 'come from difference sources' %
+ (rel.r_type, term.as_string(), oterm.as_string()))
# if term is a rewritten const, we can apply the same changes to
# all other consts inserted from the same original variable
for const in self._const_vars.get(term, ()):
--- a/server/test/unittest_msplanner.py Thu Sep 29 12:55:28 2011 +0200
+++ b/server/test/unittest_msplanner.py Thu Sep 29 13:53:34 2011 +0200
@@ -1806,15 +1806,19 @@
def test_delete_relation3(self):
repo._type_source_cache[999999] = ('Note', 'cards', 999999, 'cards')
- self._test('DELETE Y multisource_inlined_rel X WHERE X eid %(x)s, NOT (Y cw_source S, S name %(source)s)',
- [('DeleteRelationsStep',
- [('OneFetchStep',
- [('Any Y,999999 WHERE Y multisource_inlined_rel 999999, NOT EXISTS(Y cw_source S, S name "cards"), S is CWSource, Y is IN(Card, Note)',
- [{'S': 'CWSource', 'Y': 'Card'}, {'S': 'CWSource', 'Y': 'Note'}])],
- None, None, [self.system], {},
- [])]
- )],
- {'x': 999999, 'source': 'cards'})
+ self.assertRaises(
+ BadRQLQuery, self._test,
+ 'DELETE Y multisource_inlined_rel X WHERE X eid %(x)s, '
+ 'NOT (Y cw_source S, S name %(source)s)', [],
+ {'x': 999999, 'source': 'cards'})
+
+ def test_delete_relation4(self):
+ repo._type_source_cache[999999] = ('Note', 'cards', 999999, 'cards')
+ self.assertRaises(
+ BadRQLQuery, self._test,
+ 'DELETE X multisource_inlined_rel Y WHERE Y is Note, X eid %(x)s, '
+ 'NOT (Y cw_source S, S name %(source)s)', [],
+ {'x': 999999, 'source': 'cards'})
def test_delete_entity1(self):
repo._type_source_cache[999999] = ('Note', 'system', 999999, 'system')