# HG changeset patch # User Sylvain Thénault # Date 1244563471 -7200 # Node ID 933ccfce6e9183aba5f21b2c4497f9c9ef41bdcc # Parent 9e268cb6202e4ea3813e91c81493eb19a4920582 fix bug in multisource planner, w/ inlined relation diff -r 9e268cb6202e -r 933ccfce6e91 server/msplanner.py --- a/server/msplanner.py Tue Jun 09 18:03:28 2009 +0200 +++ b/server/msplanner.py Tue Jun 09 18:04:31 2009 +0200 @@ -158,6 +158,7 @@ # XXX move functions below to rql ############################################## def is_ancestor(n1, n2): + """return True if n2 is a parent scope of n1""" p = n1.parent while p is not None: if p is n2: @@ -171,17 +172,14 @@ newnode.append(part) return newnode -def same_scope(var): - """return true if the variable is always used in the same scope""" - try: - return var.stinfo['samescope'] - except KeyError: - for rel in var.stinfo['relations']: - if not rel.scope is var.scope: - var.stinfo['samescope'] = False - return False - var.stinfo['samescope'] = True - return True +def used_in_outer_scope(var, scope): + """return true if the variable is used in an outer scope of the given scope + """ + for rel in var.stinfo['relations']: + rscope = rel.scope + if not rscope is scope and is_ancestor(scope, rscope): + return True + return False ################################################################################ @@ -1227,6 +1225,7 @@ self.mayneedvar, self.hasvar = {}, {} self.use_only_defined = False self.scopes = {rqlst: newroot} + self.current_scope = rqlst if rqlst.where: rqlst = self._rqlst_accept(rqlst, rqlst.where, newroot, terms, newroot.set_where) @@ -1397,7 +1396,7 @@ return False if var.name in self.extneedsel or var.stinfo['selected']: return False - if not same_scope(var): + if not var in terms or used_in_outer_scope(var, self.current_scope): return False if any(v for v, _ in var.stinfo['attrvars'] if not v in terms): return False diff -r 9e268cb6202e -r 933ccfce6e91 server/test/unittest_msplanner.py --- a/server/test/unittest_msplanner.py Tue Jun 09 18:03:28 2009 +0200 +++ b/server/test/unittest_msplanner.py Tue Jun 09 18:04:31 2009 +0200 @@ -2073,6 +2073,44 @@ {'x': 999999}) + +class FakeVCSSource(AbstractSource): + uri = 'ccc' + support_entities = {'Card': True, 'Note': True} + support_relations = {'multisource_inlined_rel': True, + 'multisource_rel': True} + #dont_cross_relations = set(('fiche', 'in_state')) + #cross_relations = set(('multisource_crossed_rel',)) + + def syntax_tree_search(self, *args, **kwargs): + return [] + +class MSPlannerVCSSource(BasePlannerTC): + repo = repo + + def setUp(self): + self.setup() + self.add_source(FakeVCSSource, 'vcs') + self.planner = MSPlanner(self.o.schema, self.o._rqlhelper) + _test = test_plan + + def test_multisource_inlined_rel_skipped(self): + self._test('Any MAX(VC) ' + 'WHERE VC multisource_inlined_rel R2, R para %(branch)s, VC in_state S, S name "published", ' + '(EXISTS(R identity R2)) OR (EXISTS(R multisource_rel R2))', + [('FetchStep', [('Any VC WHERE VC multisource_inlined_rel R2, R para "???", (EXISTS(R identity R2)) OR (EXISTS(R multisource_rel R2)), R is Note, R2 is Note, VC is Note', + [{'R': 'Note', 'R2': 'Note', 'VC': 'Note'}])], + [self.vcs, self.system], None, + {'VC': 'table0.C0'}, + []), + ('OneFetchStep', [(u'Any MAX(VC) WHERE VC in_state S, S name "published", S is State, VC is Note', + [{'S': 'State', 'VC': 'Note'}])], + None, None, [self.system], + {'VC': 'table0.C0'}, + []) + ]) + + if __name__ == '__main__': from logilab.common.testlib import unittest_main unittest_main()