server/test/unittest_msplanner.py
branchstable
changeset 2074 9e268cb6202e
parent 1977 606923dff11b
child 2075 933ccfce6e91
equal deleted inserted replaced
2073:173c646981a7 2074:9e268cb6202e
    53                      {'X': 'File'}, {'X': 'Folder'}, {'X': 'Image'},
    53                      {'X': 'File'}, {'X': 'Folder'}, {'X': 'Image'},
    54                      {'X': 'Note'}, {'X': 'Personne'}, {'X': 'RQLExpression'},
    54                      {'X': 'Note'}, {'X': 'Personne'}, {'X': 'RQLExpression'},
    55                      {'X': 'Societe'}, {'X': 'State'}, {'X': 'SubDivision'},
    55                      {'X': 'Societe'}, {'X': 'State'}, {'X': 'SubDivision'},
    56                      {'X': 'Tag'}, {'X': 'TrInfo'}, {'X': 'Transition'}])
    56                      {'X': 'Tag'}, {'X': 'TrInfo'}, {'X': 'Transition'}])
    57 
    57 
    58 def clear_ms_caches(repo):
       
    59     clear_cache(repo, 'rel_type_sources')
       
    60     clear_cache(repo, 'can_cross_relation')
       
    61     clear_cache(repo, 'is_multi_sources_relation')
       
    62     # XXX source_defs
       
    63 
    58 
    64 # keep cnx so it's not garbage collected and the associated session is closed
    59 # keep cnx so it's not garbage collected and the associated session is closed
    65 repo, cnx = init_test_database('sqlite')
    60 repo, cnx = init_test_database('sqlite')
    66 
    61 
    67 class BaseMSPlannerTC(BasePlannerTC):
    62 class BaseMSPlannerTC(BasePlannerTC):
    73     """
    68     """
    74     repo = repo
    69     repo = repo
    75 
    70 
    76     def setUp(self):
    71     def setUp(self):
    77         #_QuerierTC.setUp(self)
    72         #_QuerierTC.setUp(self)
    78         clear_cache(repo, 'rel_type_sources')
    73         self.setup()
    79         self.o = repo.querier
       
    80         self.session = repo._sessions.values()[0]
       
    81         self.pool = self.session.set_pool()
       
    82         self.schema = self.o.schema
       
    83         # hijack Affaire security
    74         # hijack Affaire security
    84         affreadperms = list(self.schema['Affaire']._groups['read'])
    75         affreadperms = list(self.schema['Affaire']._groups['read'])
    85         self.prevrqlexpr_affaire = affreadperms[-1]
    76         self.prevrqlexpr_affaire = affreadperms[-1]
    86         # add access to type attribute so S can't be invariant
    77         # add access to type attribute so S can't be invariant
    87         affreadperms[-1] = ERQLExpression('X concerne S?, S owned_by U, S type "X"')
    78         affreadperms[-1] = ERQLExpression('X concerne S?, S owned_by U, S type "X"')
    89         # hijack CWUser security
    80         # hijack CWUser security
    90         userreadperms = list(self.schema['CWUser']._groups['read'])
    81         userreadperms = list(self.schema['CWUser']._groups['read'])
    91         self.prevrqlexpr_user = userreadperms[-1]
    82         self.prevrqlexpr_user = userreadperms[-1]
    92         userreadperms[-1] = ERQLExpression('X owned_by U')
    83         userreadperms[-1] = ERQLExpression('X owned_by U')
    93         self.schema['CWUser']._groups['read'] = tuple(userreadperms)
    84         self.schema['CWUser']._groups['read'] = tuple(userreadperms)
    94 
    85         self.add_source(FakeUserROSource, 'ldap')
    95         self.sources = self.o._repo.sources
    86         self.add_source(FakeCardSource, 'cards')
    96         self.system = self.sources[-1]
       
    97         self.sources.append(FakeUserROSource(self.o._repo, self.o.schema,
       
    98                                              {'uri': 'ldapuser'}))
       
    99         repo.sources_by_uri['ldapuser'] = self.sources[-1]
       
   100         self.ldap = self.sources[-1]
       
   101         self.sources.append(FakeCardSource(self.o._repo, self.o.schema,
       
   102                                            {'uri': 'cards'}))
       
   103         repo.sources_by_uri['cards'] = self.sources[-1]
       
   104         self.rql = self.sources[-1]
       
   105         do_monkey_patch()
       
   106         clear_ms_caches(repo)
       
   107 
    87 
   108     def tearDown(self):
    88     def tearDown(self):
   109         undo_monkey_patch()
    89         super(BaseMSPlannerTC, self).tearDown()
   110         del self.sources[-1]
       
   111         del self.sources[-1]
       
   112         del repo.sources_by_uri['ldapuser']
       
   113         del repo.sources_by_uri['cards']
       
   114         # restore hijacked security
    90         # restore hijacked security
   115         self.restore_orig_affaire_security()
    91         self.restore_orig_affaire_security()
   116         self.restore_orig_euser_security()
    92         self.restore_orig_euser_security()
   117 
    93 
   118     def restore_orig_affaire_security(self):
    94     def restore_orig_affaire_security(self):
   161 
   137 
   162     def test_simple_system_rql(self):
   138     def test_simple_system_rql(self):
   163         """retrieve Card X from both sources and return concatenation of results
   139         """retrieve Card X from both sources and return concatenation of results
   164         """
   140         """
   165         self._test('Any X, XT WHERE X is Card, X title XT',
   141         self._test('Any X, XT WHERE X is Card, X title XT',
   166                    {self.system: {'X': s[0]}, self.rql: {'X': s[0]}}, False)
   142                    {self.system: {'X': s[0]}, self.cards: {'X': s[0]}}, False)
   167 
   143 
   168     def test_simple_eid_specified(self):
   144     def test_simple_eid_specified(self):
   169         """retrieve CWUser X from system source (eid is specified, can locate the entity)
   145         """retrieve CWUser X from system source (eid is specified, can locate the entity)
   170         """
   146         """
   171         ueid = self.session.user.eid
   147         ueid = self.session.user.eid
   262 
   238 
   263     def test_exists4(self):
   239     def test_exists4(self):
   264         """
   240         """
   265         State S could come from both rql source and system source,
   241         State S could come from both rql source and system source,
   266         but since X cannot come from the rql source, the solution
   242         but since X cannot come from the rql source, the solution
   267         {self.rql : 'S'} must be removed
   243         {self.cards : 'S'} must be removed
   268         """
   244         """
   269         self._test('Any G,L WHERE X in_group G, X login L, G name "managers", '
   245         self._test('Any G,L WHERE X in_group G, X login L, G name "managers", '
   270                    'EXISTS(X copain T, T login L, T login in ("comme", "cochon")) OR '
   246                    'EXISTS(X copain T, T login L, T login in ("comme", "cochon")) OR '
   271                    'EXISTS(X in_state S, S name "pascontent", NOT X copain T2, T2 login "billy")',
   247                    'EXISTS(X in_state S, S name "pascontent", NOT X copain T2, T2 login "billy")',
   272                    {self.system: {'X': s[0], 'S': s[0], 'T2': s[0], 'T': s[0], 'G': s[0], 'copain': s[0], 'in_group': s[0]},
   248                    {self.system: {'X': s[0], 'S': s[0], 'T2': s[0], 'T': s[0], 'G': s[0], 'copain': s[0], 'in_group': s[0]},
   274                    True)
   250                    True)
   275 
   251 
   276     def test_relation_need_split(self):
   252     def test_relation_need_split(self):
   277         self._test('Any X, S WHERE X in_state S',
   253         self._test('Any X, S WHERE X in_state S',
   278                    {self.system: {'X': s[0, 1, 2], 'S': s[0, 1, 2]},
   254                    {self.system: {'X': s[0, 1, 2], 'S': s[0, 1, 2]},
   279                     self.rql: {'X': s[2], 'S': s[2]}},
   255                     self.cards: {'X': s[2], 'S': s[2]}},
   280                    True)
   256                    True)
   281 
   257 
   282     def test_not_relation_need_split(self):
   258     def test_not_relation_need_split(self):
   283         self._test('Any SN WHERE NOT X in_state S, S name SN',
   259         self._test('Any SN WHERE NOT X in_state S, S name SN',
   284                    {self.rql: {'X': s[2], 'S': s[0, 1, 2]},
   260                    {self.cards: {'X': s[2], 'S': s[0, 1, 2]},
   285                     self.system: {'X': s[0, 1, 2], 'S': s[0, 1, 2]}},
   261                     self.system: {'X': s[0, 1, 2], 'S': s[0, 1, 2]}},
   286                    True)
   262                    True)
   287 
   263 
   288     def test_not_relation_no_split_external(self):
   264     def test_not_relation_no_split_external(self):
   289         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
   265         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
   290         # similar to the above test but with an eid coming from the external source.
   266         # similar to the above test but with an eid coming from the external source.
   291         # the same plan may be used, since we won't find any record in the system source
   267         # the same plan may be used, since we won't find any record in the system source
   292         # linking 9999999 to a state
   268         # linking 9999999 to a state
   293         self._test('Any SN WHERE NOT X in_state S, X eid %(x)s, S name SN',
   269         self._test('Any SN WHERE NOT X in_state S, X eid %(x)s, S name SN',
   294                    {'x': 999999},
   270                    {'x': 999999},
   295                    {self.rql: {'x': s[0], 'S': s[0]},
   271                    {self.cards: {'x': s[0], 'S': s[0]},
   296                     self.system: {'x': s[0], 'S': s[0]}},
   272                     self.system: {'x': s[0], 'S': s[0]}},
   297                    False)
   273                    False)
   298 
   274 
   299     def test_relation_restriction_ambigous_need_split(self):
   275     def test_relation_restriction_ambigous_need_split(self):
   300         self._test('Any X,T WHERE X in_state S, S name "pending", T tags X',
   276         self._test('Any X,T WHERE X in_state S, S name "pending", T tags X',
   301                    {self.system: {'X': s[0, 1, 2], 'S': s[0, 1, 2], 'T': s[0, 1, 2], 'tags': s[0, 1, 2]},
   277                    {self.system: {'X': s[0, 1, 2], 'S': s[0, 1, 2], 'T': s[0, 1, 2], 'tags': s[0, 1, 2]},
   302                     self.rql: {'X': s[2], 'S': s[2]}},
   278                     self.cards: {'X': s[2], 'S': s[2]}},
   303                    True)
   279                    True)
   304 
   280 
   305     def test_simplified_var(self):
   281     def test_simplified_var(self):
   306         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
   282         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
   307         self._test('Any U WHERE U in_group G, (G name IN ("managers", "logilab") OR (X require_permission P?, P name "bla", P require_group G)), X eid %(x)s, U eid %(u)s',
   283         self._test('Any U WHERE U in_group G, (G name IN ("managers", "logilab") OR (X require_permission P?, P name "bla", P require_group G)), X eid %(x)s, U eid %(u)s',
   321     def test_crossed_relation_eid_1_needattr(self):
   297     def test_crossed_relation_eid_1_needattr(self):
   322         repo._type_source_cache[999999] = ('Note', 'system', 999999)
   298         repo._type_source_cache[999999] = ('Note', 'system', 999999)
   323         ueid = self.session.user.eid
   299         ueid = self.session.user.eid
   324         self._test('Any Y,T WHERE X eid %(x)s, X multisource_crossed_rel Y, Y type T',
   300         self._test('Any Y,T WHERE X eid %(x)s, X multisource_crossed_rel Y, Y type T',
   325                    {'x': 999999,},
   301                    {'x': 999999,},
   326                    {self.rql: {'Y': s[0]}, self.system: {'Y': s[0], 'x': s[0]}},
   302                    {self.cards: {'Y': s[0]}, self.system: {'Y': s[0], 'x': s[0]}},
   327                    True)
   303                    True)
   328 
   304 
   329     def test_crossed_relation_eid_1_invariant(self):
   305     def test_crossed_relation_eid_1_invariant(self):
   330         repo._type_source_cache[999999] = ('Note', 'system', 999999)
   306         repo._type_source_cache[999999] = ('Note', 'system', 999999)
   331         self._test('Any Y WHERE X eid %(x)s, X multisource_crossed_rel Y',
   307         self._test('Any Y WHERE X eid %(x)s, X multisource_crossed_rel Y',
   335 
   311 
   336     def test_crossed_relation_eid_2_invariant(self):
   312     def test_crossed_relation_eid_2_invariant(self):
   337         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
   313         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
   338         self._test('Any Y WHERE X eid %(x)s, X multisource_crossed_rel Y',
   314         self._test('Any Y WHERE X eid %(x)s, X multisource_crossed_rel Y',
   339                    {'x': 999999,},
   315                    {'x': 999999,},
   340                    {self.rql: {'Y': s[0], 'multisource_crossed_rel': s[0], 'x': s[0]},
   316                    {self.cards: {'Y': s[0], 'multisource_crossed_rel': s[0], 'x': s[0]},
   341                     self.system: {'Y': s[0], 'multisource_crossed_rel': s[0], 'x': s[0]}},
   317                     self.system: {'Y': s[0], 'multisource_crossed_rel': s[0], 'x': s[0]}},
   342                    False)
   318                    False)
   343 
   319 
   344     def test_version_crossed_depends_on_1(self):
   320     def test_version_crossed_depends_on_1(self):
   345         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
   321         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
   346         self._test('Any X,AD,AE WHERE E eid %(x)s, E multisource_crossed_rel X, X in_state AD, AD name AE',
   322         self._test('Any X,AD,AE WHERE E eid %(x)s, E multisource_crossed_rel X, X in_state AD, AD name AE',
   347                    {'x': 999999},
   323                    {'x': 999999},
   348                    {self.rql: {'X': s[0], 'AD': s[0], 'multisource_crossed_rel': s[0], 'x': s[0]},
   324                    {self.cards: {'X': s[0], 'AD': s[0], 'multisource_crossed_rel': s[0], 'x': s[0]},
   349                     self.system: {'X': s[0], 'AD': s[0], 'multisource_crossed_rel': s[0], 'x': s[0]}},
   325                     self.system: {'X': s[0], 'AD': s[0], 'multisource_crossed_rel': s[0], 'x': s[0]}},
   350                    True)
   326                    True)
   351 
   327 
   352     def test_version_crossed_depends_on_2(self):
   328     def test_version_crossed_depends_on_2(self):
   353         repo._type_source_cache[999999] = ('Note', 'system', 999999)
   329         repo._type_source_cache[999999] = ('Note', 'system', 999999)
   354         self._test('Any X,AD,AE WHERE E eid %(x)s, E multisource_crossed_rel X, X in_state AD, AD name AE',
   330         self._test('Any X,AD,AE WHERE E eid %(x)s, E multisource_crossed_rel X, X in_state AD, AD name AE',
   355                    {'x': 999999},
   331                    {'x': 999999},
   356                    {self.rql: {'X': s[0], 'AD': s[0]},
   332                    {self.cards: {'X': s[0], 'AD': s[0]},
   357                     self.system: {'X': s[0], 'AD': s[0], 'x': s[0]}},
   333                     self.system: {'X': s[0], 'AD': s[0], 'x': s[0]}},
   358                     True)
   334                     True)
   359 
   335 
   360     def test_simplified_var_3(self):
   336     def test_simplified_var_3(self):
   361         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
   337         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
   362         repo._type_source_cache[999998] = ('State', 'cards', 999998)
   338         repo._type_source_cache[999998] = ('State', 'cards', 999998)
   363         self._test('Any S,T WHERE S eid %(s)s, N eid %(n)s, N type T, N is Note, S is State',
   339         self._test('Any S,T WHERE S eid %(s)s, N eid %(n)s, N type T, N is Note, S is State',
   364                    {'n': 999999, 's': 999998},
   340                    {'n': 999999, 's': 999998},
   365                    {self.rql: {'s': s[0], 'N': s[0]}}, False)
   341                    {self.cards: {'s': s[0], 'N': s[0]}}, False)
   366 
   342 
   367 
   343 
   368 
   344 
   369 class MSPlannerTC(BaseMSPlannerTC):
   345 class MSPlannerTC(BaseMSPlannerTC):
   370 
   346 
   439     def test_simple_system_rql(self):
   415     def test_simple_system_rql(self):
   440         """retrieve Card X from both sources and return concatenation of results
   416         """retrieve Card X from both sources and return concatenation of results
   441         """
   417         """
   442         self._test('Any X, XT WHERE X is Card, X title XT',
   418         self._test('Any X, XT WHERE X is Card, X title XT',
   443                    [('OneFetchStep', [('Any X,XT WHERE X is Card, X title XT', [{'X': 'Card', 'XT': 'String'}])],
   419                    [('OneFetchStep', [('Any X,XT WHERE X is Card, X title XT', [{'X': 'Card', 'XT': 'String'}])],
   444                      None, None, [self.rql, self.system], {}, [])])
   420                      None, None, [self.cards, self.system], {}, [])])
   445 
   421 
   446     def test_simple_eid_specified(self):
   422     def test_simple_eid_specified(self):
   447         """retrieve CWUser X from system source (eid is specified, can locate the entity)
   423         """retrieve CWUser X from system source (eid is specified, can locate the entity)
   448         """
   424         """
   449         ueid = self.session.user.eid
   425         ueid = self.session.user.eid
   666     def test_complex_typed_aggregat(self):
   642     def test_complex_typed_aggregat(self):
   667         self._test('Any MAX(X) WHERE X is Card',
   643         self._test('Any MAX(X) WHERE X is Card',
   668                    [('AggrStep', 'Any MAX(X)', None, None, 'table0',  None,
   644                    [('AggrStep', 'Any MAX(X)', None, None, 'table0',  None,
   669                      [('FetchStep',
   645                      [('FetchStep',
   670                        [('Any MAX(X) WHERE X is Card', [{'X': 'Card'}])],
   646                        [('Any MAX(X) WHERE X is Card', [{'X': 'Card'}])],
   671                        [self.rql, self.system], {}, {'MAX(X)': 'table0.C0'}, [])
   647                        [self.cards, self.system], {}, {'MAX(X)': 'table0.C0'}, [])
   672                       ])
   648                       ])
   673                     ])
   649                     ])
   674 
   650 
   675     def test_complex_greater_eid(self):
   651     def test_complex_greater_eid(self):
   676         self._test('Any X WHERE X eid > 12',
   652         self._test('Any X WHERE X eid > 12',
   704 
   680 
   705 
   681 
   706     def test_3sources_ambigous(self):
   682     def test_3sources_ambigous(self):
   707         self._test('Any X,T WHERE X owned_by U, U login "syt", X title T',
   683         self._test('Any X,T WHERE X owned_by U, U login "syt", X title T',
   708                    [('FetchStep', [('Any X,T WHERE X title T, X is Card', [{'X': 'Card', 'T': 'String'}])],
   684                    [('FetchStep', [('Any X,T WHERE X title T, X is Card', [{'X': 'Card', 'T': 'String'}])],
   709                      [self.rql, self.system], None,
   685                      [self.cards, self.system], None,
   710                      {'T': 'table0.C1', 'X': 'table0.C0', 'X.title': 'table0.C1'}, []),
   686                      {'T': 'table0.C1', 'X': 'table0.C0', 'X.title': 'table0.C1'}, []),
   711                     ('FetchStep', [('Any U WHERE U login "syt", U is CWUser', [{'U': 'CWUser'}])],
   687                     ('FetchStep', [('Any U WHERE U login "syt", U is CWUser', [{'U': 'CWUser'}])],
   712                      [self.ldap, self.system], None,
   688                      [self.ldap, self.system], None,
   713                      {'U': 'table1.C0'}, []),
   689                      {'U': 'table1.C0'}, []),
   714                     ('UnionStep', None, None, [
   690                     ('UnionStep', None, None, [
   728         self._test('Any V, MAX(VR) WHERE V is Card, V creation_date VR, '
   704         self._test('Any V, MAX(VR) WHERE V is Card, V creation_date VR, '
   729                    '(V creation_date TODAY OR (V creation_date < TODAY AND NOT EXISTS('
   705                    '(V creation_date TODAY OR (V creation_date < TODAY AND NOT EXISTS('
   730                    'X is Card, X creation_date < TODAY, X creation_date >= VR)))',
   706                    'X is Card, X creation_date < TODAY, X creation_date >= VR)))',
   731                    [('FetchStep', [('Any VR WHERE X creation_date < TODAY, X creation_date >= VR, X is Card',
   707                    [('FetchStep', [('Any VR WHERE X creation_date < TODAY, X creation_date >= VR, X is Card',
   732                                     [{'X': 'Card', 'VR': 'Datetime'}])],
   708                                     [{'X': 'Card', 'VR': 'Datetime'}])],
   733                      [self.rql, self.system], None,
   709                      [self.cards, self.system], None,
   734                      {'VR': 'table0.C0', 'X.creation_date': 'table0.C0'}, []),
   710                      {'VR': 'table0.C0', 'X.creation_date': 'table0.C0'}, []),
   735                     ('FetchStep', [('Any V,VR WHERE V creation_date VR, V is Card',
   711                     ('FetchStep', [('Any V,VR WHERE V creation_date VR, V is Card',
   736                                     [{'VR': 'Datetime', 'V': 'Card'}])],
   712                                     [{'VR': 'Datetime', 'V': 'Card'}])],
   737                      [self.rql, self.system], None,
   713                      [self.cards, self.system], None,
   738                      {'VR': 'table1.C1', 'V': 'table1.C0', 'V.creation_date': 'table1.C1'}, []),
   714                      {'VR': 'table1.C1', 'V': 'table1.C0', 'V.creation_date': 'table1.C1'}, []),
   739                     ('OneFetchStep', [('Any V,MAX(VR) WHERE V creation_date VR, (V creation_date TODAY) OR (V creation_date < TODAY, NOT EXISTS(X creation_date >= VR, X is Card)), V is Card',
   715                     ('OneFetchStep', [('Any V,MAX(VR) WHERE V creation_date VR, (V creation_date TODAY) OR (V creation_date < TODAY, NOT EXISTS(X creation_date >= VR, X is Card)), V is Card',
   740                                        [{'X': 'Card', 'VR': 'Datetime', 'V': 'Card'}])],
   716                                        [{'X': 'Card', 'VR': 'Datetime', 'V': 'Card'}])],
   741                      None, None, [self.system],
   717                      None, None, [self.system],
   742                      {'VR': 'table1.C1', 'V': 'table1.C0', 'V.creation_date': 'table1.C1', 'X.creation_date': 'table0.C0'}, [])
   718                      {'VR': 'table1.C1', 'V': 'table1.C0', 'V.creation_date': 'table1.C1', 'X.creation_date': 'table0.C0'}, [])
   747         self._test('Any X, R WHERE X is Note, X in_state S, X type R, '
   723         self._test('Any X, R WHERE X is Note, X in_state S, X type R, '
   748                    'NOT EXISTS(Y is Note, Y in_state S, Y type R, X identity Y)',
   724                    'NOT EXISTS(Y is Note, Y in_state S, Y type R, X identity Y)',
   749                    [('OneFetchStep', [('Any X,R WHERE X is Note, X in_state S, X type R, NOT EXISTS(Y is Note, Y in_state S, Y type R, X identity Y), S is State',
   725                    [('OneFetchStep', [('Any X,R WHERE X is Note, X in_state S, X type R, NOT EXISTS(Y is Note, Y in_state S, Y type R, X identity Y), S is State',
   750                                        [{'Y': 'Note', 'X': 'Note', 'S': 'State', 'R': 'String'}])],
   726                                        [{'Y': 'Note', 'X': 'Note', 'S': 'State', 'R': 'String'}])],
   751                      None, None,
   727                      None, None,
   752                      [self.rql, self.system], {}, [])
   728                      [self.cards, self.system], {}, [])
   753                     ])
   729                     ])
   754 
   730 
   755     def test_not_identity(self):
   731     def test_not_identity(self):
   756         # both system and rql support all variables, can be
   732         # both system and rql support all variables, can be
   757         self._test('Any X WHERE NOT X identity U, U eid %s' % self.session.user.eid,
   733         self._test('Any X WHERE NOT X identity U, U eid %s' % self.session.user.eid,
   764     def test_outer_supported_rel2(self):
   740     def test_outer_supported_rel2(self):
   765         self._test('Any X, MAX(R) GROUPBY X WHERE X in_state S, X login R, '
   741         self._test('Any X, MAX(R) GROUPBY X WHERE X in_state S, X login R, '
   766                    'NOT EXISTS(Y is Note, Y in_state S, Y type R)',
   742                    'NOT EXISTS(Y is Note, Y in_state S, Y type R)',
   767                    [('FetchStep', [('Any A,R WHERE Y in_state A, Y type R, A is State, Y is Note',
   743                    [('FetchStep', [('Any A,R WHERE Y in_state A, Y type R, A is State, Y is Note',
   768                                     [{'Y': 'Note', 'A': 'State', 'R': 'String'}])],
   744                                     [{'Y': 'Note', 'A': 'State', 'R': 'String'}])],
   769                      [self.rql, self.system], None,
   745                      [self.cards, self.system], None,
   770                      {'A': 'table0.C0', 'R': 'table0.C1', 'Y.type': 'table0.C1'}, []),
   746                      {'A': 'table0.C0', 'R': 'table0.C1', 'Y.type': 'table0.C1'}, []),
   771                     ('FetchStep', [('Any X,R WHERE X login R, X is CWUser', [{'X': 'CWUser', 'R': 'String'}])],
   747                     ('FetchStep', [('Any X,R WHERE X login R, X is CWUser', [{'X': 'CWUser', 'R': 'String'}])],
   772                      [self.ldap, self.system], None,
   748                      [self.ldap, self.system], None,
   773                      {'X': 'table1.C0', 'X.login': 'table1.C1', 'R': 'table1.C1'}, []),
   749                      {'X': 'table1.C0', 'X.login': 'table1.C1', 'R': 'table1.C1'}, []),
   774                     ('OneFetchStep', [('Any X,MAX(R) GROUPBY X WHERE X in_state S, X login R, NOT EXISTS(Y type R, S identity A, A is State, Y is Note), S is State, X is CWUser',
   750                     ('OneFetchStep', [('Any X,MAX(R) GROUPBY X WHERE X in_state S, X login R, NOT EXISTS(Y type R, S identity A, A is State, Y is Note), S is State, X is CWUser',
   780     def test_security_has_text(self):
   756     def test_security_has_text(self):
   781         # use a guest user
   757         # use a guest user
   782         self.session = self._user_session()[1]
   758         self.session = self._user_session()[1]
   783         self._test('Any X WHERE X has_text "bla"',
   759         self._test('Any X WHERE X has_text "bla"',
   784                    [('FetchStep', [('Any E WHERE E type "X", E is Note', [{'E': 'Note'}])],
   760                    [('FetchStep', [('Any E WHERE E type "X", E is Note', [{'E': 'Note'}])],
   785                      [self.rql, self.system], None, {'E': 'table0.C0'}, []),
   761                      [self.cards, self.system], None, {'E': 'table0.C0'}, []),
   786                     ('UnionStep', None, None,
   762                     ('UnionStep', None, None,
   787                      [('OneFetchStep',
   763                      [('OneFetchStep',
   788                        [(u'Any X WHERE X has_text "bla", (EXISTS(X owned_by 5)) OR ((((EXISTS(D concerne C?, C owned_by 5, C type "X", X identity D, C is Division, D is Affaire)) OR (EXISTS(H concerne G?, G owned_by 5, G type "X", X identity H, G is SubDivision, H is Affaire))) OR (EXISTS(I concerne F?, F owned_by 5, F type "X", X identity I, F is Societe, I is Affaire))) OR (EXISTS(J concerne E?, E owned_by 5, X identity J, E is Note, J is Affaire))), X is Affaire',
   764                        [(u'Any X WHERE X has_text "bla", (EXISTS(X owned_by 5)) OR ((((EXISTS(D concerne C?, C owned_by 5, C type "X", X identity D, C is Division, D is Affaire)) OR (EXISTS(H concerne G?, G owned_by 5, G type "X", X identity H, G is SubDivision, H is Affaire))) OR (EXISTS(I concerne F?, F owned_by 5, F type "X", X identity I, F is Societe, I is Affaire))) OR (EXISTS(J concerne E?, E owned_by 5, X identity J, E is Note, J is Affaire))), X is Affaire',
   789                          [{'C': 'Division', 'E': 'Note', 'D': 'Affaire', 'G': 'SubDivision', 'F': 'Societe', 'I': 'Affaire', 'H': 'Affaire', 'J': 'Affaire', 'X': 'Affaire'}])],
   765                          [{'C': 'Division', 'E': 'Note', 'D': 'Affaire', 'G': 'SubDivision', 'F': 'Societe', 'I': 'Affaire', 'H': 'Affaire', 'J': 'Affaire', 'X': 'Affaire'}])],
   790                        None, None, [self.system], {'E': 'table0.C0'}, []),
   766                        None, None, [self.system], {'E': 'table0.C0'}, []),
   807         # use a guest user
   783         # use a guest user
   808         self.session = self._user_session()[1]
   784         self.session = self._user_session()[1]
   809         # note: same as the above query but because of the subquery usage, the display differs (not printing solutions for each union)
   785         # note: same as the above query but because of the subquery usage, the display differs (not printing solutions for each union)
   810         self._test('Any X LIMIT 10 OFFSET 10 WHERE X has_text "bla"',
   786         self._test('Any X LIMIT 10 OFFSET 10 WHERE X has_text "bla"',
   811                    [('FetchStep', [('Any E WHERE E type "X", E is Note', [{'E': 'Note'}])],
   787                    [('FetchStep', [('Any E WHERE E type "X", E is Note', [{'E': 'Note'}])],
   812                       [self.rql, self.system], None, {'E': 'table1.C0'}, []),
   788                       [self.cards, self.system], None, {'E': 'table1.C0'}, []),
   813                      ('UnionFetchStep', [
   789                      ('UnionFetchStep', [
   814                          ('FetchStep', [('Any X WHERE X has_text "bla", (EXISTS(X owned_by 5)) OR ((((EXISTS(D concerne C?, C owned_by 5, C type "X", X identity D, C is Division, D is Affaire)) OR (EXISTS(H concerne G?, G owned_by 5, G type "X", X identity H, G is SubDivision, H is Affaire))) OR (EXISTS(I concerne F?, F owned_by 5, F type "X", X identity I, F is Societe, I is Affaire))) OR (EXISTS(J concerne E?, E owned_by 5, X identity J, E is Note, J is Affaire))), X is Affaire',
   790                          ('FetchStep', [('Any X WHERE X has_text "bla", (EXISTS(X owned_by 5)) OR ((((EXISTS(D concerne C?, C owned_by 5, C type "X", X identity D, C is Division, D is Affaire)) OR (EXISTS(H concerne G?, G owned_by 5, G type "X", X identity H, G is SubDivision, H is Affaire))) OR (EXISTS(I concerne F?, F owned_by 5, F type "X", X identity I, F is Societe, I is Affaire))) OR (EXISTS(J concerne E?, E owned_by 5, X identity J, E is Note, J is Affaire))), X is Affaire',
   815                                             [{'C': 'Division', 'E': 'Note', 'D': 'Affaire', 'G': 'SubDivision', 'F': 'Societe', 'I': 'Affaire', 'H': 'Affaire', 'J': 'Affaire', 'X': 'Affaire'}])],
   791                                             [{'C': 'Division', 'E': 'Note', 'D': 'Affaire', 'G': 'SubDivision', 'F': 'Societe', 'I': 'Affaire', 'H': 'Affaire', 'J': 'Affaire', 'X': 'Affaire'}])],
   816                           [self.system], {'E': 'table1.C0'}, {'X': 'table0.C0'}, []),
   792                           [self.system], {'E': 'table1.C0'}, {'X': 'table0.C0'}, []),
   817                          ('FetchStep',
   793                          ('FetchStep',
   884     def test_security_complex_aggregat(self):
   860     def test_security_complex_aggregat(self):
   885         # use a guest user
   861         # use a guest user
   886         self.session = self._user_session()[1]
   862         self.session = self._user_session()[1]
   887         self._test('Any MAX(X)',
   863         self._test('Any MAX(X)',
   888                    [('FetchStep', [('Any E WHERE E type "X", E is Note', [{'E': 'Note'}])],
   864                    [('FetchStep', [('Any E WHERE E type "X", E is Note', [{'E': 'Note'}])],
   889                      [self.rql, self.system],  None, {'E': 'table1.C0'}, []),
   865                      [self.cards, self.system],  None, {'E': 'table1.C0'}, []),
   890                     ('FetchStep', [('Any X WHERE X is CWUser', [{'X': 'CWUser'}])],
   866                     ('FetchStep', [('Any X WHERE X is CWUser', [{'X': 'CWUser'}])],
   891                      [self.ldap, self.system], None, {'X': 'table2.C0'}, []),
   867                      [self.ldap, self.system], None, {'X': 'table2.C0'}, []),
   892                     ('UnionFetchStep', [
   868                     ('UnionFetchStep', [
   893                         ('FetchStep', [('Any X WHERE EXISTS(X owned_by 5), X is Basket', [{'X': 'Basket'}])],
   869                         ('FetchStep', [('Any X WHERE EXISTS(X owned_by 5), X is Basket', [{'X': 'Basket'}])],
   894                           [self.system], {}, {'X': 'table0.C0'}, []),
   870                           [self.system], {}, {'X': 'table0.C0'}, []),
   895                         ('UnionFetchStep',
   871                         ('UnionFetchStep',
   896                          [('FetchStep', [('Any X WHERE X is IN(Card, Note, State)',
   872                          [('FetchStep', [('Any X WHERE X is IN(Card, Note, State)',
   897                                           [{'X': 'Card'}, {'X': 'Note'}, {'X': 'State'}])],
   873                                           [{'X': 'Card'}, {'X': 'Note'}, {'X': 'State'}])],
   898                            [self.rql, self.system], {}, {'X': 'table0.C0'}, []),
   874                            [self.cards, self.system], {}, {'X': 'table0.C0'}, []),
   899                           ('FetchStep',
   875                           ('FetchStep',
   900                            [('Any X WHERE X is IN(Bookmark, CWAttribute, CWCache, CWConstraint, CWConstraintType, CWEType, CWGroup, CWPermission, CWProperty, CWRType, CWRelation, Comment, Division, Email, EmailAddress, EmailPart, EmailThread, File, Folder, Image, Personne, RQLExpression, Societe, SubDivision, Tag, TrInfo, Transition)',
   876                            [('Any X WHERE X is IN(Bookmark, CWAttribute, CWCache, CWConstraint, CWConstraintType, CWEType, CWGroup, CWPermission, CWProperty, CWRType, CWRelation, Comment, Division, Email, EmailAddress, EmailPart, EmailThread, File, Folder, Image, Personne, RQLExpression, Societe, SubDivision, Tag, TrInfo, Transition)',
   901                              sorted([{'X': 'Bookmark'}, {'X': 'Comment'}, {'X': 'Division'},
   877                              sorted([{'X': 'Bookmark'}, {'X': 'Comment'}, {'X': 'Division'},
   902                                       {'X': 'CWCache'}, {'X': 'CWConstraint'}, {'X': 'CWConstraintType'},
   878                                       {'X': 'CWCache'}, {'X': 'CWConstraint'}, {'X': 'CWConstraintType'},
   903                                       {'X': 'CWEType'}, {'X': 'CWAttribute'}, {'X': 'CWGroup'},
   879                                       {'X': 'CWEType'}, {'X': 'CWAttribute'}, {'X': 'CWGroup'},
   923         # use a guest user
   899         # use a guest user
   924         self.session = self._user_session()[1]
   900         self.session = self._user_session()[1]
   925         self._test('Any ET, COUNT(X) GROUPBY ET ORDERBY ET WHERE X is ET',
   901         self._test('Any ET, COUNT(X) GROUPBY ET ORDERBY ET WHERE X is ET',
   926                    [('FetchStep', [('Any X WHERE X is IN(Card, Note, State)',
   902                    [('FetchStep', [('Any X WHERE X is IN(Card, Note, State)',
   927                                     [{'X': 'Card'}, {'X': 'Note'}, {'X': 'State'}])],
   903                                     [{'X': 'Card'}, {'X': 'Note'}, {'X': 'State'}])],
   928                      [self.rql, self.system], None, {'X': 'table1.C0'}, []),
   904                      [self.cards, self.system], None, {'X': 'table1.C0'}, []),
   929                     ('FetchStep', [('Any E WHERE E type "X", E is Note', [{'E': 'Note'}])],
   905                     ('FetchStep', [('Any E WHERE E type "X", E is Note', [{'E': 'Note'}])],
   930                      [self.rql, self.system],  None, {'E': 'table2.C0'}, []),
   906                      [self.cards, self.system],  None, {'E': 'table2.C0'}, []),
   931                     ('FetchStep', [('Any X WHERE X is CWUser', [{'X': 'CWUser'}])],
   907                     ('FetchStep', [('Any X WHERE X is CWUser', [{'X': 'CWUser'}])],
   932                      [self.ldap, self.system], None, {'X': 'table3.C0'}, []),
   908                      [self.ldap, self.system], None, {'X': 'table3.C0'}, []),
   933                     ('UnionFetchStep',
   909                     ('UnionFetchStep',
   934                      [('FetchStep', [('Any ET,X WHERE X is ET, EXISTS(X owned_by 5), ET is CWEType, X is Basket',
   910                      [('FetchStep', [('Any ET,X WHERE X is ET, EXISTS(X owned_by 5), ET is CWEType, X is Basket',
   935                                       [{'ET': 'CWEType', 'X': 'Basket'}])],
   911                                       [{'ET': 'CWEType', 'X': 'Basket'}])],
   996         # use a guest user
   972         # use a guest user
   997         self.session = self._user_session()[1]
   973         self.session = self._user_session()[1]
   998         self._test('Any X, XT WHERE X is Card, X owned_by U, X title XT, U login "syt"',
   974         self._test('Any X, XT WHERE X is Card, X owned_by U, X title XT, U login "syt"',
   999                    [('FetchStep',
   975                    [('FetchStep',
  1000                      [('Any X,XT WHERE X title XT, X is Card', [{'X': 'Card', 'XT': 'String'}])],
   976                      [('Any X,XT WHERE X title XT, X is Card', [{'X': 'Card', 'XT': 'String'}])],
  1001                      [self.rql, self.system], None, {'X': 'table0.C0', 'X.title': 'table0.C1', 'XT': 'table0.C1'}, []),
   977                      [self.cards, self.system], None, {'X': 'table0.C0', 'X.title': 'table0.C1', 'XT': 'table0.C1'}, []),
  1002                     ('FetchStep',
   978                     ('FetchStep',
  1003                      [('Any U WHERE U login "syt", U is CWUser', [{'U': 'CWUser'}])],
   979                      [('Any U WHERE U login "syt", U is CWUser', [{'U': 'CWUser'}])],
  1004                      [self.ldap, self.system], None, {'U': 'table1.C0'}, []),
   980                      [self.ldap, self.system], None, {'U': 'table1.C0'}, []),
  1005                     ('OneFetchStep',
   981                     ('OneFetchStep',
  1006                      [('Any X,XT WHERE X owned_by U, X title XT, EXISTS(U owned_by 5), U is CWUser, X is Card',
   982                      [('Any X,XT WHERE X owned_by U, X title XT, EXISTS(U owned_by 5), U is CWUser, X is Card',
  1014         # use a guest user
   990         # use a guest user
  1015         self.session = self._user_session()[1]
   991         self.session = self._user_session()[1]
  1016         self._test('Any X, XT WHERE X is Card, X owned_by U, X title XT, U login "syt"',
   992         self._test('Any X, XT WHERE X is Card, X owned_by U, X title XT, U login "syt"',
  1017                    [('FetchStep',
   993                    [('FetchStep',
  1018                      [('Any X,XT WHERE X title XT, X is Card', [{'X': 'Card', 'XT': 'String'}])],
   994                      [('Any X,XT WHERE X title XT, X is Card', [{'X': 'Card', 'XT': 'String'}])],
  1019                      [self.rql, self.system], None, {'X': 'table0.C0', 'X.title': 'table0.C1', 'XT': 'table0.C1'}, []),
   995                      [self.cards, self.system], None, {'X': 'table0.C0', 'X.title': 'table0.C1', 'XT': 'table0.C1'}, []),
  1020                     ('OneFetchStep',
   996                     ('OneFetchStep',
  1021                      [('Any X,XT WHERE X owned_by U, X title XT, U login "syt", EXISTS(U identity 5), U is CWUser, X is Card',
   997                      [('Any X,XT WHERE X owned_by U, X title XT, U login "syt", EXISTS(U identity 5), U is CWUser, X is Card',
  1022                        [{'U': 'CWUser', 'X': 'Card', 'XT': 'String'}])],
   998                        [{'U': 'CWUser', 'X': 'Card', 'XT': 'String'}])],
  1023                      None, None, [self.system], {'X': 'table0.C0', 'X.title': 'table0.C1', 'XT': 'table0.C1'}, [])
   999                      None, None, [self.system], {'X': 'table0.C0', 'X.title': 'table0.C1', 'XT': 'table0.C1'}, [])
  1024                     ])
  1000                     ])
  1032                      [('Any U,L WHERE U identity 5, U login L, U is CWUser',
  1008                      [('Any U,L WHERE U identity 5, U login L, U is CWUser',
  1033                        [{'L': 'String', u'U': 'CWUser'}])],
  1009                        [{'L': 'String', u'U': 'CWUser'}])],
  1034                      [self.system], {}, {'L': 'table0.C1', 'U': 'table0.C0', 'U.login': 'table0.C1'}, []),
  1010                      [self.system], {}, {'L': 'table0.C1', 'U': 'table0.C0', 'U.login': 'table0.C1'}, []),
  1035                     ('FetchStep',
  1011                     ('FetchStep',
  1036                      [('Any X,XT WHERE X title XT, X is Card', [{'X': 'Card', 'XT': 'String'}])],
  1012                      [('Any X,XT WHERE X title XT, X is Card', [{'X': 'Card', 'XT': 'String'}])],
  1037                      [self.rql, self.system], None, {'X': 'table1.C0', 'X.title': 'table1.C1', 'XT': 'table1.C1'}, []),
  1013                      [self.cards, self.system], None, {'X': 'table1.C0', 'X.title': 'table1.C1', 'XT': 'table1.C1'}, []),
  1038                     ('OneFetchStep',
  1014                     ('OneFetchStep',
  1039                      [('Any X,XT,U WHERE X owned_by U?, X title XT, X is Card',
  1015                      [('Any X,XT,U WHERE X owned_by U?, X title XT, X is Card',
  1040                        [{'X': 'Card', 'XT': 'String'}])],
  1016                        [{'X': 'Card', 'XT': 'String'}])],
  1041                      None, None, [self.system], {'L': 'table0.C1',
  1017                      None, None, [self.system], {'L': 'table0.C1',
  1042                                                  'U': 'table0.C0',
  1018                                                  'U': 'table0.C0',
  1049         # use a guest user
  1025         # use a guest user
  1050         self.session = self._user_session()[1]
  1026         self.session = self._user_session()[1]
  1051         self._test('Any X, XT LIMIT 10 OFFSET 10 WHERE X is Card, X owned_by U, X title XT, U login "syt"',
  1027         self._test('Any X, XT LIMIT 10 OFFSET 10 WHERE X is Card, X owned_by U, X title XT, U login "syt"',
  1052                    [('FetchStep',
  1028                    [('FetchStep',
  1053                      [('Any X,XT WHERE X title XT, X is Card', [{'X': 'Card', 'XT': 'String'}])],
  1029                      [('Any X,XT WHERE X title XT, X is Card', [{'X': 'Card', 'XT': 'String'}])],
  1054                      [self.rql, self.system], None, {'X': 'table0.C0', 'X.title': 'table0.C1', 'XT': 'table0.C1'}, []),
  1030                      [self.cards, self.system], None, {'X': 'table0.C0', 'X.title': 'table0.C1', 'XT': 'table0.C1'}, []),
  1055                     ('FetchStep',
  1031                     ('FetchStep',
  1056                      [('Any U WHERE U login "syt", U is CWUser', [{'U': 'CWUser'}])],
  1032                      [('Any U WHERE U login "syt", U is CWUser', [{'U': 'CWUser'}])],
  1057                      [self.ldap, self.system], None, {'U': 'table1.C0'}, []),
  1033                      [self.ldap, self.system], None, {'U': 'table1.C0'}, []),
  1058                     ('OneFetchStep',
  1034                     ('OneFetchStep',
  1059                      [('Any X,XT LIMIT 10 OFFSET 10 WHERE X owned_by U, X title XT, EXISTS(U owned_by 5), U is CWUser, X is Card',
  1035                      [('Any X,XT LIMIT 10 OFFSET 10 WHERE X owned_by U, X title XT, EXISTS(U owned_by 5), U is CWUser, X is Card',
  1168                        ('OneFetchStep', [('Any X,S WHERE X in_state S, S is State, X is IN(Affaire, CWUser)',
  1144                        ('OneFetchStep', [('Any X,S WHERE X in_state S, S is State, X is IN(Affaire, CWUser)',
  1169                                           [{'X': 'Affaire', 'S': 'State'}, {'X': 'CWUser', 'S': 'State'}])],
  1145                                           [{'X': 'Affaire', 'S': 'State'}, {'X': 'CWUser', 'S': 'State'}])],
  1170                         None, None, [self.system], {}, []),
  1146                         None, None, [self.system], {}, []),
  1171                        ('OneFetchStep', [('Any X,S WHERE X in_state S, S is State, X is Note',
  1147                        ('OneFetchStep', [('Any X,S WHERE X in_state S, S is State, X is Note',
  1172                                           [{'X': 'Note', 'S': 'State'}])],
  1148                                           [{'X': 'Note', 'S': 'State'}])],
  1173                         None, None, [self.rql, self.system], {}, []),
  1149                         None, None, [self.cards, self.system], {}, []),
  1174                     ])])
  1150                     ])])
  1175 
  1151 
  1176     def test_relation_selection_need_split(self):
  1152     def test_relation_selection_need_split(self):
  1177         self._test('Any X,S,U WHERE X in_state S, X todo_by U',
  1153         self._test('Any X,S,U WHERE X in_state S, X todo_by U',
  1178                    [('FetchStep', [('Any X,S WHERE X in_state S, S is State, X is Note',
  1154                    [('FetchStep', [('Any X,S WHERE X in_state S, S is State, X is Note',
  1179                                     [{'X': 'Note', 'S': 'State'}])],
  1155                                     [{'X': 'Note', 'S': 'State'}])],
  1180                      [self.rql, self.system], None, {'X': 'table0.C0', 'S': 'table0.C1'}, []),
  1156                      [self.cards, self.system], None, {'X': 'table0.C0', 'S': 'table0.C1'}, []),
  1181                      ('UnionStep', None, None,
  1157                      ('UnionStep', None, None,
  1182                       [('OneFetchStep', [('Any X,S,U WHERE X in_state S, X todo_by U, S is State, U is CWUser, X is Note',
  1158                       [('OneFetchStep', [('Any X,S,U WHERE X in_state S, X todo_by U, S is State, U is CWUser, X is Note',
  1183                                           [{'X': 'Note', 'S': 'State', 'U': 'CWUser'}])],
  1159                                           [{'X': 'Note', 'S': 'State', 'U': 'CWUser'}])],
  1184                         None, None, [self.system], {'X': 'table0.C0', 'S': 'table0.C1'}, []),
  1160                         None, None, [self.system], {'X': 'table0.C0', 'S': 'table0.C1'}, []),
  1185                        ('OneFetchStep', [('Any X,S,U WHERE X in_state S, X todo_by U, S is State, U is Personne, X is Affaire',
  1161                        ('OneFetchStep', [('Any X,S,U WHERE X in_state S, X todo_by U, S is State, U is Personne, X is Affaire',
  1190 
  1166 
  1191     def test_relation_restriction_need_split(self):
  1167     def test_relation_restriction_need_split(self):
  1192         self._test('Any X,U WHERE X in_state S, S name "pending", X todo_by U',
  1168         self._test('Any X,U WHERE X in_state S, S name "pending", X todo_by U',
  1193                    [('FetchStep', [('Any X WHERE X in_state S, S name "pending", S is State, X is Note',
  1169                    [('FetchStep', [('Any X WHERE X in_state S, S name "pending", S is State, X is Note',
  1194                                     [{'X': 'Note', 'S': 'State'}])],
  1170                                     [{'X': 'Note', 'S': 'State'}])],
  1195                      [self.rql, self.system], None, {'X': 'table0.C0'}, []),
  1171                      [self.cards, self.system], None, {'X': 'table0.C0'}, []),
  1196                      ('UnionStep', None, None,
  1172                      ('UnionStep', None, None,
  1197                       [('OneFetchStep', [('Any X,U WHERE X todo_by U, U is CWUser, X is Note',
  1173                       [('OneFetchStep', [('Any X,U WHERE X todo_by U, U is CWUser, X is Note',
  1198                                           [{'X': 'Note', 'U': 'CWUser'}])],
  1174                                           [{'X': 'Note', 'U': 'CWUser'}])],
  1199                         None, None, [self.system], {'X': 'table0.C0'}, []),
  1175                         None, None, [self.system], {'X': 'table0.C0'}, []),
  1200                        ('OneFetchStep', [('Any X,U WHERE X in_state S, S name "pending", X todo_by U, S is State, U is Personne, X is Affaire',
  1176                        ('OneFetchStep', [('Any X,U WHERE X in_state S, S name "pending", X todo_by U, S is State, U is Personne, X is Affaire',
  1205 
  1181 
  1206     def test_relation_restriction_ambigous_need_split(self):
  1182     def test_relation_restriction_ambigous_need_split(self):
  1207         self._test('Any X,T WHERE X in_state S, S name "pending", T tags X',
  1183         self._test('Any X,T WHERE X in_state S, S name "pending", T tags X',
  1208                    [('FetchStep', [('Any X WHERE X in_state S, S name "pending", S is State, X is Note',
  1184                    [('FetchStep', [('Any X WHERE X in_state S, S name "pending", S is State, X is Note',
  1209                                     [{'X': 'Note', 'S': 'State'}])],
  1185                                     [{'X': 'Note', 'S': 'State'}])],
  1210                      [self.rql, self.system], None, {'X': 'table0.C0'}, []),
  1186                      [self.cards, self.system], None, {'X': 'table0.C0'}, []),
  1211                     ('UnionStep', None, None, [
  1187                     ('UnionStep', None, None, [
  1212                         ('OneFetchStep', [('Any X,T WHERE T tags X, T is Tag, X is Note',
  1188                         ('OneFetchStep', [('Any X,T WHERE T tags X, T is Tag, X is Note',
  1213                                            [{'X': 'Note', 'T': 'Tag'}])],
  1189                                            [{'X': 'Note', 'T': 'Tag'}])],
  1214                          None, None,
  1190                          None, None,
  1215                          [self.system], {'X': 'table0.C0'}, []),
  1191                          [self.system], {'X': 'table0.C0'}, []),
  1229         # in the source where %(x)s is not coming from and will be removed during rql
  1205         # in the source where %(x)s is not coming from and will be removed during rql
  1230         # generation for the external source
  1206         # generation for the external source
  1231         self._test('Any SN WHERE NOT X in_state S, X eid %(x)s, S name SN',
  1207         self._test('Any SN WHERE NOT X in_state S, X eid %(x)s, S name SN',
  1232                    [('OneFetchStep', [('Any SN WHERE NOT 5 in_state S, S name SN, S is State',
  1208                    [('OneFetchStep', [('Any SN WHERE NOT 5 in_state S, S name SN, S is State',
  1233                                        [{'S': 'State', 'SN': 'String'}])],
  1209                                        [{'S': 'State', 'SN': 'String'}])],
  1234                      None, None, [self.rql, self.system], {}, [])],
  1210                      None, None, [self.cards, self.system], {}, [])],
  1235                    {'x': ueid})
  1211                    {'x': ueid})
  1236 
  1212 
  1237     def test_not_relation_no_split_external(self):
  1213     def test_not_relation_no_split_external(self):
  1238         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1214         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1239         # similar to the above test but with an eid coming from the external source.
  1215         # similar to the above test but with an eid coming from the external source.
  1240         # the same plan may be used, since we won't find any record in the system source
  1216         # the same plan may be used, since we won't find any record in the system source
  1241         # linking 9999999 to a state
  1217         # linking 9999999 to a state
  1242         self._test('Any SN WHERE NOT X in_state S, X eid %(x)s, S name SN',
  1218         self._test('Any SN WHERE NOT X in_state S, X eid %(x)s, S name SN',
  1243                    [('OneFetchStep', [('Any SN WHERE NOT 999999 in_state S, S name SN, S is State',
  1219                    [('OneFetchStep', [('Any SN WHERE NOT 999999 in_state S, S name SN, S is State',
  1244                                        [{'S': 'State', 'SN': 'String'}])],
  1220                                        [{'S': 'State', 'SN': 'String'}])],
  1245                      None, None, [self.rql, self.system], {}, [])],
  1221                      None, None, [self.cards, self.system], {}, [])],
  1246                    {'x': 999999})
  1222                    {'x': 999999})
  1247 
  1223 
  1248     def test_not_relation_need_split(self):
  1224     def test_not_relation_need_split(self):
  1249         self._test('Any SN WHERE NOT X in_state S, S name SN',
  1225         self._test('Any SN WHERE NOT X in_state S, S name SN',
  1250                    [('FetchStep', [('Any SN,S WHERE S name SN, S is State',
  1226                    [('FetchStep', [('Any SN,S WHERE S name SN, S is State',
  1251                                     [{'S': 'State', 'SN': 'String'}])],
  1227                                     [{'S': 'State', 'SN': 'String'}])],
  1252                      [self.rql, self.system], None, {'S': 'table0.C1', 'S.name': 'table0.C0', 'SN': 'table0.C0'},
  1228                      [self.cards, self.system], None, {'S': 'table0.C1', 'S.name': 'table0.C0', 'SN': 'table0.C0'},
  1253                      []),
  1229                      []),
  1254                     ('IntersectStep', None, None,
  1230                     ('IntersectStep', None, None,
  1255                      [('OneFetchStep',
  1231                      [('OneFetchStep',
  1256                        [('Any SN WHERE NOT X in_state S, S name SN, S is State, X is Note',
  1232                        [('Any SN WHERE NOT X in_state S, S name SN, S is State, X is Note',
  1257                          [{'S': 'State', 'SN': 'String', 'X': 'Note'}])],
  1233                          [{'S': 'State', 'SN': 'String', 'X': 'Note'}])],
  1258                        None, None, [self.rql, self.system], {},
  1234                        None, None, [self.cards, self.system], {},
  1259                        []),
  1235                        []),
  1260                       ('OneFetchStep',
  1236                       ('OneFetchStep',
  1261                        [('Any SN WHERE NOT X in_state S, S name SN, S is State, X is IN(Affaire, CWUser)',
  1237                        [('Any SN WHERE NOT X in_state S, S name SN, S is State, X is IN(Affaire, CWUser)',
  1262                          [{'S': 'State', 'SN': 'String', 'X': 'Affaire'},
  1238                          [{'S': 'State', 'SN': 'String', 'X': 'Affaire'},
  1263                           {'S': 'State', 'SN': 'String', 'X': 'CWUser'}])],
  1239                           {'S': 'State', 'SN': 'String', 'X': 'CWUser'}])],
  1268     def test_external_attributes_and_relation(self):
  1244     def test_external_attributes_and_relation(self):
  1269         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1245         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1270         self._test('Any A,B,C,D WHERE A eid %(x)s,A creation_date B,A modification_date C, A todo_by D?',
  1246         self._test('Any A,B,C,D WHERE A eid %(x)s,A creation_date B,A modification_date C, A todo_by D?',
  1271                    [('FetchStep', [('Any A,B,C WHERE A eid 999999, A creation_date B, A modification_date C, A is Note',
  1247                    [('FetchStep', [('Any A,B,C WHERE A eid 999999, A creation_date B, A modification_date C, A is Note',
  1272                                     [{'A': 'Note', 'C': 'Datetime', 'B': 'Datetime'}])],
  1248                                     [{'A': 'Note', 'C': 'Datetime', 'B': 'Datetime'}])],
  1273                      [self.rql], None,
  1249                      [self.cards], None,
  1274                      {'A': 'table0.C0', 'A.creation_date': 'table0.C1', 'A.modification_date': 'table0.C2', 'C': 'table0.C2', 'B': 'table0.C1'}, []),
  1250                      {'A': 'table0.C0', 'A.creation_date': 'table0.C1', 'A.modification_date': 'table0.C2', 'C': 'table0.C2', 'B': 'table0.C1'}, []),
  1275                     #('FetchStep', [('Any D WHERE D is CWUser', [{'D': 'CWUser'}])],
  1251                     #('FetchStep', [('Any D WHERE D is CWUser', [{'D': 'CWUser'}])],
  1276                     # [self.ldap, self.system], None, {'D': 'table1.C0'}, []),
  1252                     # [self.ldap, self.system], None, {'D': 'table1.C0'}, []),
  1277                     ('OneFetchStep', [('Any A,B,C,D WHERE A creation_date B, A modification_date C, A todo_by D?, A is Note, D is CWUser',
  1253                     ('OneFetchStep', [('Any A,B,C,D WHERE A creation_date B, A modification_date C, A todo_by D?, A is Note, D is CWUser',
  1278                                        [{'A': 'Note', 'C': 'Datetime', 'B': 'Datetime', 'D': 'CWUser'}])],
  1254                                        [{'A': 'Note', 'C': 'Datetime', 'B': 'Datetime', 'D': 'CWUser'}])],
  1297 
  1273 
  1298     def test_has_text_3(self):
  1274     def test_has_text_3(self):
  1299         self._test('Any X WHERE X has_text "toto", X title "zoubidou"',
  1275         self._test('Any X WHERE X has_text "toto", X title "zoubidou"',
  1300                    [('FetchStep', [(u'Any X WHERE X title "zoubidou", X is Card',
  1276                    [('FetchStep', [(u'Any X WHERE X title "zoubidou", X is Card',
  1301                                     [{'X': 'Card'}])],
  1277                                     [{'X': 'Card'}])],
  1302                      [self.rql, self.system], None, {'X': 'table0.C0'}, []),
  1278                      [self.cards, self.system], None, {'X': 'table0.C0'}, []),
  1303                     ('UnionStep', None, None, [
  1279                     ('UnionStep', None, None, [
  1304                         ('OneFetchStep', [(u'Any X WHERE X has_text "toto", X is Card',
  1280                         ('OneFetchStep', [(u'Any X WHERE X has_text "toto", X is Card',
  1305                                            [{'X': 'Card'}])],
  1281                                            [{'X': 'Card'}])],
  1306                          None, None, [self.system], {'X': 'table0.C0'}, []),
  1282                          None, None, [self.system], {'X': 'table0.C0'}, []),
  1307                         ('OneFetchStep', [(u'Any X WHERE X has_text "toto", X title "zoubidou", X is EmailThread',
  1283                         ('OneFetchStep', [(u'Any X WHERE X has_text "toto", X title "zoubidou", X is EmailThread',
  1313     def test_sort_func(self):
  1289     def test_sort_func(self):
  1314         self._test('Note X ORDERBY DUMB_SORT(RF) WHERE X type RF',
  1290         self._test('Note X ORDERBY DUMB_SORT(RF) WHERE X type RF',
  1315                    [('AggrStep', 'Any X ORDERBY DUMB_SORT(RF)', None, None, 'table0', None, [
  1291                    [('AggrStep', 'Any X ORDERBY DUMB_SORT(RF)', None, None, 'table0', None, [
  1316                        ('FetchStep', [('Any X,RF WHERE X type RF, X is Note',
  1292                        ('FetchStep', [('Any X,RF WHERE X type RF, X is Note',
  1317                                        [{'X': 'Note', 'RF': 'String'}])],
  1293                                        [{'X': 'Note', 'RF': 'String'}])],
  1318                         [self.rql, self.system], {}, {'X': 'table0.C0', 'X.type': 'table0.C1', 'RF': 'table0.C1'}, []),
  1294                         [self.cards, self.system], {}, {'X': 'table0.C0', 'X.type': 'table0.C1', 'RF': 'table0.C1'}, []),
  1319                        ])
  1295                        ])
  1320                     ])
  1296                     ])
  1321 
  1297 
  1322     def test_ambigous_sort_func(self):
  1298     def test_ambigous_sort_func(self):
  1323         self._test('Any X ORDERBY DUMB_SORT(RF) WHERE X title RF',
  1299         self._test('Any X ORDERBY DUMB_SORT(RF) WHERE X title RF',
  1324                    [('AggrStep', 'Any X ORDERBY DUMB_SORT(RF)',
  1300                    [('AggrStep', 'Any X ORDERBY DUMB_SORT(RF)',
  1325                      None, None, 'table0', None,
  1301                      None, None, 'table0', None,
  1326                      [('FetchStep', [('Any X,RF WHERE X title RF, X is Card',
  1302                      [('FetchStep', [('Any X,RF WHERE X title RF, X is Card',
  1327                                       [{'X': 'Card', 'RF': 'String'}])],
  1303                                       [{'X': 'Card', 'RF': 'String'}])],
  1328                        [self.rql, self.system], {},
  1304                        [self.cards, self.system], {},
  1329                        {'X': 'table0.C0', 'X.title': 'table0.C1', 'RF': 'table0.C1'}, []),
  1305                        {'X': 'table0.C0', 'X.title': 'table0.C1', 'RF': 'table0.C1'}, []),
  1330                       ('FetchStep', [('Any X,RF WHERE X title RF, X is IN(Bookmark, EmailThread)',
  1306                       ('FetchStep', [('Any X,RF WHERE X title RF, X is IN(Bookmark, EmailThread)',
  1331                                       [{'RF': 'String', 'X': 'Bookmark'},
  1307                                       [{'RF': 'String', 'X': 'Bookmark'},
  1332                                        {'RF': 'String', 'X': 'EmailThread'}])],
  1308                                        {'RF': 'String', 'X': 'EmailThread'}])],
  1333                        [self.system], {},
  1309                        [self.system], {},
  1337 
  1313 
  1338     def test_attr_unification_1(self):
  1314     def test_attr_unification_1(self):
  1339         self._test('Any X,Y WHERE X is Bookmark, Y is Card, X title T, Y title T',
  1315         self._test('Any X,Y WHERE X is Bookmark, Y is Card, X title T, Y title T',
  1340                    [('FetchStep',
  1316                    [('FetchStep',
  1341                      [('Any Y,T WHERE Y title T, Y is Card', [{'T': 'String', 'Y': 'Card'}])],
  1317                      [('Any Y,T WHERE Y title T, Y is Card', [{'T': 'String', 'Y': 'Card'}])],
  1342                      [self.rql, self.system], None,
  1318                      [self.cards, self.system], None,
  1343                      {'T': 'table0.C1', 'Y': 'table0.C0', 'Y.title': 'table0.C1'}, []),
  1319                      {'T': 'table0.C1', 'Y': 'table0.C0', 'Y.title': 'table0.C1'}, []),
  1344                     ('OneFetchStep',
  1320                     ('OneFetchStep',
  1345                      [('Any X,Y WHERE X title T, Y title T, X is Bookmark, Y is Card',
  1321                      [('Any X,Y WHERE X title T, Y title T, X is Bookmark, Y is Card',
  1346                        [{'T': 'String', 'X': 'Bookmark', 'Y': 'Card'}])],
  1322                        [{'T': 'String', 'X': 'Bookmark', 'Y': 'Card'}])],
  1347                      None, None, [self.system],
  1323                      None, None, [self.system],
  1350 
  1326 
  1351     def test_attr_unification_2(self):
  1327     def test_attr_unification_2(self):
  1352         self._test('Any X,Y WHERE X is Note, Y is Card, X type T, Y title T',
  1328         self._test('Any X,Y WHERE X is Note, Y is Card, X type T, Y title T',
  1353                    [('FetchStep',
  1329                    [('FetchStep',
  1354                      [('Any X,T WHERE X type T, X is Note', [{'T': 'String', 'X': 'Note'}])],
  1330                      [('Any X,T WHERE X type T, X is Note', [{'T': 'String', 'X': 'Note'}])],
  1355                      [self.rql, self.system], None,
  1331                      [self.cards, self.system], None,
  1356                      {'T': 'table0.C1', 'X': 'table0.C0', 'X.type': 'table0.C1'}, []),
  1332                      {'T': 'table0.C1', 'X': 'table0.C0', 'X.type': 'table0.C1'}, []),
  1357                     ('FetchStep',
  1333                     ('FetchStep',
  1358                      [('Any Y,T WHERE Y title T, Y is Card', [{'T': 'String', 'Y': 'Card'}])],
  1334                      [('Any Y,T WHERE Y title T, Y is Card', [{'T': 'String', 'Y': 'Card'}])],
  1359                      [self.rql, self.system], None,
  1335                      [self.cards, self.system], None,
  1360                      {'T': 'table1.C1', 'Y': 'table1.C0', 'Y.title': 'table1.C1'}, []),
  1336                      {'T': 'table1.C1', 'Y': 'table1.C0', 'Y.title': 'table1.C1'}, []),
  1361                     ('OneFetchStep',
  1337                     ('OneFetchStep',
  1362                      [('Any X,Y WHERE X type T, Y title T, X is Note, Y is Card',
  1338                      [('Any X,Y WHERE X type T, Y title T, X is Note, Y is Card',
  1363                        [{'T': 'String', 'X': 'Note', 'Y': 'Card'}])],
  1339                        [{'T': 'String', 'X': 'Note', 'Y': 'Card'}])],
  1364                      None, None, [self.system],
  1340                      None, None, [self.system],
  1370     def test_attr_unification_neq_1(self):
  1346     def test_attr_unification_neq_1(self):
  1371         self._test('Any X,Y WHERE X is Bookmark, Y is Card, X creation_date D, Y creation_date > D',
  1347         self._test('Any X,Y WHERE X is Bookmark, Y is Card, X creation_date D, Y creation_date > D',
  1372                    [('FetchStep',
  1348                    [('FetchStep',
  1373                      [('Any Y,D WHERE Y creation_date > D, Y is Card',
  1349                      [('Any Y,D WHERE Y creation_date > D, Y is Card',
  1374                        [{'D': 'Datetime', 'Y': 'Card'}])],
  1350                        [{'D': 'Datetime', 'Y': 'Card'}])],
  1375                      [self.rql,self.system], None,
  1351                      [self.cards,self.system], None,
  1376                      {'D': 'table0.C1', 'Y': 'table0.C0', 'Y.creation_date': 'table0.C1'}, []),
  1352                      {'D': 'table0.C1', 'Y': 'table0.C0', 'Y.creation_date': 'table0.C1'}, []),
  1377                     ('OneFetchStep',
  1353                     ('OneFetchStep',
  1378                      [('Any X,Y WHERE X creation_date D, Y creation_date > D, X is Bookmark, Y is Card',
  1354                      [('Any X,Y WHERE X creation_date D, Y creation_date > D, X is Bookmark, Y is Card',
  1379                        [{'D': 'Datetime', 'X': 'Bookmark', 'Y': 'Card'}])], None, None,
  1355                        [{'D': 'Datetime', 'X': 'Bookmark', 'Y': 'Card'}])], None, None,
  1380                      [self.system],
  1356                      [self.system],
  1413                         'X': 'table0.C0',
  1389                         'X': 'table0.C0',
  1414                         'X.name': 'table0.C1',
  1390                         'X.name': 'table0.C1',
  1415                         'X.title': 'table0.C1'}, []),
  1391                         'X.title': 'table0.C1'}, []),
  1416                       ('FetchStep', [('Any X,T WHERE X is Card, X title T',
  1392                       ('FetchStep', [('Any X,T WHERE X is Card, X title T',
  1417                                       [{'T': 'String', 'X': 'Card'}])],
  1393                                       [{'T': 'String', 'X': 'Card'}])],
  1418                        [self.rql, self.system], {},
  1394                        [self.cards, self.system], {},
  1419                        {'N': 'table0.C1',
  1395                        {'N': 'table0.C1',
  1420                         'T': 'table0.C1',
  1396                         'T': 'table0.C1',
  1421                         'X': 'table0.C0',
  1397                         'X': 'table0.C0',
  1422                         'X.name': 'table0.C1',
  1398                         'X.name': 'table0.C1',
  1423                         'X.title': 'table0.C1'}, []),
  1399                         'X.title': 'table0.C1'}, []),
  1457 
  1433 
  1458     def test_crossed_relation_eid_1_needattr(self):
  1434     def test_crossed_relation_eid_1_needattr(self):
  1459         repo._type_source_cache[999999] = ('Note', 'system', 999999)
  1435         repo._type_source_cache[999999] = ('Note', 'system', 999999)
  1460         self._test('Any Y,T WHERE X eid %(x)s, X multisource_crossed_rel Y, Y type T',
  1436         self._test('Any Y,T WHERE X eid %(x)s, X multisource_crossed_rel Y, Y type T',
  1461                    [('FetchStep', [('Any Y,T WHERE Y type T, Y is Note', [{'T': 'String', 'Y': 'Note'}])],
  1437                    [('FetchStep', [('Any Y,T WHERE Y type T, Y is Note', [{'T': 'String', 'Y': 'Note'}])],
  1462                      [self.rql, self.system], None,
  1438                      [self.cards, self.system], None,
  1463                      {'T': 'table0.C1', 'Y': 'table0.C0', 'Y.type': 'table0.C1'}, []),
  1439                      {'T': 'table0.C1', 'Y': 'table0.C0', 'Y.type': 'table0.C1'}, []),
  1464                     ('OneFetchStep', [('Any Y,T WHERE 999999 multisource_crossed_rel Y, Y type T, Y is Note',
  1440                     ('OneFetchStep', [('Any Y,T WHERE 999999 multisource_crossed_rel Y, Y type T, Y is Note',
  1465                                        [{'T': 'String', 'Y': 'Note'}])],
  1441                                        [{'T': 'String', 'Y': 'Note'}])],
  1466                      None, None, [self.system],
  1442                      None, None, [self.system],
  1467                      {'T': 'table0.C1', 'Y': 'table0.C0', 'Y.type': 'table0.C1'}, []),
  1443                      {'T': 'table0.C1', 'Y': 'table0.C0', 'Y.type': 'table0.C1'}, []),
  1470 
  1446 
  1471     def test_crossed_relation_eid_2_invariant(self):
  1447     def test_crossed_relation_eid_2_invariant(self):
  1472         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1448         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1473         self._test('Any Y WHERE X eid %(x)s, X multisource_crossed_rel Y',
  1449         self._test('Any Y WHERE X eid %(x)s, X multisource_crossed_rel Y',
  1474                    [('OneFetchStep', [('Any Y WHERE 999999 multisource_crossed_rel Y, Y is Note', [{'Y': 'Note'}])],
  1450                    [('OneFetchStep', [('Any Y WHERE 999999 multisource_crossed_rel Y, Y is Note', [{'Y': 'Note'}])],
  1475                       None, None, [self.rql, self.system], {}, [])
  1451                       None, None, [self.cards, self.system], {}, [])
  1476                     ],
  1452                     ],
  1477                    {'x': 999999,})
  1453                    {'x': 999999,})
  1478 
  1454 
  1479     def test_crossed_relation_eid_2_needattr(self):
  1455     def test_crossed_relation_eid_2_needattr(self):
  1480         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1456         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1481         self._test('Any Y,T WHERE X eid %(x)s, X multisource_crossed_rel Y, Y type T',
  1457         self._test('Any Y,T WHERE X eid %(x)s, X multisource_crossed_rel Y, Y type T',
  1482                    [('FetchStep', [('Any Y,T WHERE Y type T, Y is Note', [{'T': 'String', 'Y': 'Note'}])],
  1458                    [('FetchStep', [('Any Y,T WHERE Y type T, Y is Note', [{'T': 'String', 'Y': 'Note'}])],
  1483                      [self.rql, self.system], None,
  1459                      [self.cards, self.system], None,
  1484                      {'T': 'table0.C1', 'Y': 'table0.C0', 'Y.type': 'table0.C1'}, []),
  1460                      {'T': 'table0.C1', 'Y': 'table0.C0', 'Y.type': 'table0.C1'}, []),
  1485                     ('UnionStep', None, None,
  1461                     ('UnionStep', None, None,
  1486                      [('OneFetchStep', [('Any Y,T WHERE 999999 multisource_crossed_rel Y, Y type T, Y is Note',
  1462                      [('OneFetchStep', [('Any Y,T WHERE 999999 multisource_crossed_rel Y, Y type T, Y is Note',
  1487                                          [{'T': 'String', 'Y': 'Note'}])],
  1463                                          [{'T': 'String', 'Y': 'Note'}])],
  1488                        None, None, [self.rql], None,
  1464                        None, None, [self.cards], None,
  1489                        []),
  1465                        []),
  1490                       ('OneFetchStep', [('Any Y,T WHERE 999999 multisource_crossed_rel Y, Y type T, Y is Note',
  1466                       ('OneFetchStep', [('Any Y,T WHERE 999999 multisource_crossed_rel Y, Y type T, Y is Note',
  1491                                          [{'T': 'String', 'Y': 'Note'}])],
  1467                                          [{'T': 'String', 'Y': 'Note'}])],
  1492                        None, None, [self.system],
  1468                        None, None, [self.system],
  1493                        {'T': 'table0.C1', 'Y': 'table0.C0', 'Y.type': 'table0.C1'},
  1469                        {'T': 'table0.C1', 'Y': 'table0.C0', 'Y.type': 'table0.C1'},
  1497 
  1473 
  1498     def test_crossed_relation_eid_not_1(self):
  1474     def test_crossed_relation_eid_not_1(self):
  1499         repo._type_source_cache[999999] = ('Note', 'system', 999999)
  1475         repo._type_source_cache[999999] = ('Note', 'system', 999999)
  1500         self._test('Any Y WHERE X eid %(x)s, NOT X multisource_crossed_rel Y',
  1476         self._test('Any Y WHERE X eid %(x)s, NOT X multisource_crossed_rel Y',
  1501                    [('FetchStep', [('Any Y WHERE Y is Note', [{'Y': 'Note'}])],
  1477                    [('FetchStep', [('Any Y WHERE Y is Note', [{'Y': 'Note'}])],
  1502                      [self.rql, self.system], None, {'Y': 'table0.C0'}, []),
  1478                      [self.cards, self.system], None, {'Y': 'table0.C0'}, []),
  1503                     ('OneFetchStep', [('Any Y WHERE NOT 999999 multisource_crossed_rel Y, Y is Note',
  1479                     ('OneFetchStep', [('Any Y WHERE NOT 999999 multisource_crossed_rel Y, Y is Note',
  1504                                        [{'Y': 'Note'}])],
  1480                                        [{'Y': 'Note'}])],
  1505                      None, None, [self.system],
  1481                      None, None, [self.system],
  1506                      {'Y': 'table0.C0'},  [])],
  1482                      {'Y': 'table0.C0'},  [])],
  1507                    {'x': 999999,})
  1483                    {'x': 999999,})
  1514 
  1490 
  1515     def test_crossed_relation_base_XXXFIXME(self):
  1491     def test_crossed_relation_base_XXXFIXME(self):
  1516         repo._type_source_cache[999999] = ('Note', 'system', 999999)
  1492         repo._type_source_cache[999999] = ('Note', 'system', 999999)
  1517         self._test('Any X,Y,T WHERE X multisource_crossed_rel Y, Y type T, X type T',
  1493         self._test('Any X,Y,T WHERE X multisource_crossed_rel Y, Y type T, X type T',
  1518                    [('FetchStep', [('Any X,T WHERE X type T, X is Note', [{'T': 'String', 'X': 'Note'}])],
  1494                    [('FetchStep', [('Any X,T WHERE X type T, X is Note', [{'T': 'String', 'X': 'Note'}])],
  1519                      [self.rql, self.system], None,
  1495                      [self.cards, self.system], None,
  1520                      {'T': 'table0.C1', 'X': 'table0.C0', 'X.type': 'table0.C1'}, []),
  1496                      {'T': 'table0.C1', 'X': 'table0.C0', 'X.type': 'table0.C1'}, []),
  1521                     ('FetchStep',  [('Any Y,T WHERE Y type T, Y is Note', [{'T': 'String', 'Y': 'Note'}])],
  1497                     ('FetchStep',  [('Any Y,T WHERE Y type T, Y is Note', [{'T': 'String', 'Y': 'Note'}])],
  1522                      [self.rql, self.system], None,
  1498                      [self.cards, self.system], None,
  1523                      {'T': 'table1.C1', 'Y': 'table1.C0', 'Y.type': 'table1.C1'},  []),
  1499                      {'T': 'table1.C1', 'Y': 'table1.C0', 'Y.type': 'table1.C1'},  []),
  1524                     ('UnionStep', None,  None,
  1500                     ('UnionStep', None,  None,
  1525                      [('OneFetchStep', [('Any X,Y,T WHERE X multisource_crossed_rel Y, Y type T, X type T, X is Note, Y is Note',
  1501                      [('OneFetchStep', [('Any X,Y,T WHERE X multisource_crossed_rel Y, Y type T, X type T, X is Note, Y is Note',
  1526                                          [{'T': 'String', 'X': 'Note', 'Y': 'Note'}])],
  1502                                          [{'T': 'String', 'X': 'Note', 'Y': 'Note'}])],
  1527                        None, None, [self.rql], None,
  1503                        None, None, [self.cards], None,
  1528                        []),
  1504                        []),
  1529                       ('OneFetchStep', [('Any X,Y,T WHERE X multisource_crossed_rel Y, Y type T, X type T, X is Note, Y is Note',
  1505                       ('OneFetchStep', [('Any X,Y,T WHERE X multisource_crossed_rel Y, Y type T, X type T, X is Note, Y is Note',
  1530                                          [{'T': 'String', 'X': 'Note', 'Y': 'Note'}])],
  1506                                          [{'T': 'String', 'X': 'Note', 'Y': 'Note'}])],
  1531                        None, None, [self.system],
  1507                        None, None, [self.system],
  1532                        {'T': 'table1.C1', 'X': 'table0.C0', 'X.type': 'table0.C1',
  1508                        {'T': 'table1.C1', 'X': 'table0.C0', 'X.type': 'table0.C1',
  1541         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1517         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1542         repo._type_source_cache[999998] = ('State', 'system', None)
  1518         repo._type_source_cache[999998] = ('State', 'system', None)
  1543         self._test('INSERT Note X: X in_state S, X type T WHERE S eid %(s)s, N eid %(n)s, N type T',
  1519         self._test('INSERT Note X: X in_state S, X type T WHERE S eid %(s)s, N eid %(n)s, N type T',
  1544                    [('FetchStep', [('Any T WHERE N eid 999999, N type T, N is Note',
  1520                    [('FetchStep', [('Any T WHERE N eid 999999, N type T, N is Note',
  1545                                     [{'N': 'Note', 'T': 'String'}])],
  1521                                     [{'N': 'Note', 'T': 'String'}])],
  1546                      [self.rql], None, {'N.type': 'table0.C0', 'T': 'table0.C0'}, []),
  1522                      [self.cards], None, {'N.type': 'table0.C0', 'T': 'table0.C0'}, []),
  1547                     ('InsertStep',
  1523                     ('InsertStep',
  1548                      [('RelationsStep',
  1524                      [('RelationsStep',
  1549                        [('OneFetchStep', [('Any 999998,T WHERE N type T, N is Note',
  1525                        [('OneFetchStep', [('Any 999998,T WHERE N type T, N is Note',
  1550                                            [{'N': 'Note', 'T': 'String'}])],
  1526                                            [{'N': 'Note', 'T': 'String'}])],
  1551                         None, None, [self.system],
  1527                         None, None, [self.system],
  1558         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1534         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1559         repo._type_source_cache[999998] = ('State', 'system', None)
  1535         repo._type_source_cache[999998] = ('State', 'system', None)
  1560         self._test('INSERT Note X: X in_state S, X type T, X migrated_from N WHERE S eid %(s)s, N eid %(n)s, N type T',
  1536         self._test('INSERT Note X: X in_state S, X type T, X migrated_from N WHERE S eid %(s)s, N eid %(n)s, N type T',
  1561                    [('FetchStep', [('Any T,N WHERE N eid 999999, N type T, N is Note',
  1537                    [('FetchStep', [('Any T,N WHERE N eid 999999, N type T, N is Note',
  1562                                     [{'N': 'Note', 'T': 'String'}])],
  1538                                     [{'N': 'Note', 'T': 'String'}])],
  1563                      [self.rql], None, {'N': 'table0.C1', 'N.type': 'table0.C0', 'T': 'table0.C0'}, []),
  1539                      [self.cards], None, {'N': 'table0.C1', 'N.type': 'table0.C0', 'T': 'table0.C0'}, []),
  1564                     ('InsertStep',
  1540                     ('InsertStep',
  1565                      [('RelationsStep',
  1541                      [('RelationsStep',
  1566                        [('OneFetchStep', [('Any 999998,T,N WHERE N type T, N is Note',
  1542                        [('OneFetchStep', [('Any 999998,T,N WHERE N type T, N is Note',
  1567                                            [{'N': 'Note', 'T': 'String'}])],
  1543                                            [{'N': 'Note', 'T': 'String'}])],
  1568                          None, None, [self.system],
  1544                          None, None, [self.system],
  1578         self._test('INSERT Note X: X in_state S, X type T WHERE S eid %(s)s, N eid %(n)s, N type T',
  1554         self._test('INSERT Note X: X in_state S, X type T WHERE S eid %(s)s, N eid %(n)s, N type T',
  1579                    [('InsertStep',
  1555                    [('InsertStep',
  1580                      [('RelationsStep',
  1556                      [('RelationsStep',
  1581                        [('OneFetchStep', [('Any 999998,T WHERE N eid 999999, N type T, N is Note',
  1557                        [('OneFetchStep', [('Any 999998,T WHERE N eid 999999, N type T, N is Note',
  1582                                            [{'N': 'Note', 'T': 'String'}])],
  1558                                            [{'N': 'Note', 'T': 'String'}])],
  1583                          None, None, [self.rql], {}, [])]
  1559                          None, None, [self.cards], {}, [])]
  1584                        )]
  1560                        )]
  1585                      )],
  1561                      )],
  1586                    {'n': 999999, 's': 999998})
  1562                    {'n': 999999, 's': 999998})
  1587 
  1563 
  1588     def test_insert_simplified_var_4(self):
  1564     def test_insert_simplified_var_4(self):
  1728     def test_nonregr2(self):
  1704     def test_nonregr2(self):
  1729         treid = self.session.user.latest_trinfo().eid
  1705         treid = self.session.user.latest_trinfo().eid
  1730         self._test('Any X ORDERBY D DESC WHERE E eid %(x)s, E wf_info_for X, X modification_date D',
  1706         self._test('Any X ORDERBY D DESC WHERE E eid %(x)s, E wf_info_for X, X modification_date D',
  1731                    [('FetchStep', [('Any X,D WHERE X modification_date D, X is Note',
  1707                    [('FetchStep', [('Any X,D WHERE X modification_date D, X is Note',
  1732                                     [{'X': 'Note', 'D': 'Datetime'}])],
  1708                                     [{'X': 'Note', 'D': 'Datetime'}])],
  1733                      [self.rql, self.system], None, {'X': 'table0.C0', 'X.modification_date': 'table0.C1', 'D': 'table0.C1'}, []),
  1709                      [self.cards, self.system], None, {'X': 'table0.C0', 'X.modification_date': 'table0.C1', 'D': 'table0.C1'}, []),
  1734                     ('FetchStep', [('Any X,D WHERE X modification_date D, X is CWUser',
  1710                     ('FetchStep', [('Any X,D WHERE X modification_date D, X is CWUser',
  1735                                     [{'X': 'CWUser', 'D': 'Datetime'}])],
  1711                                     [{'X': 'CWUser', 'D': 'Datetime'}])],
  1736                      [self.ldap, self.system], None, {'X': 'table1.C0', 'X.modification_date': 'table1.C1', 'D': 'table1.C1'}, []),
  1712                      [self.ldap, self.system], None, {'X': 'table1.C0', 'X.modification_date': 'table1.C1', 'D': 'table1.C1'}, []),
  1737                     ('AggrStep', 'Any X ORDERBY D DESC', None, None, 'table2', None, [
  1713                     ('AggrStep', 'Any X ORDERBY D DESC', None, None, 'table2', None, [
  1738                         ('FetchStep', [('Any X,D WHERE E eid %s, E wf_info_for X, X modification_date D, E is TrInfo, X is Affaire'%treid,
  1714                         ('FetchStep', [('Any X,D WHERE E eid %s, E wf_info_for X, X modification_date D, E is TrInfo, X is Affaire'%treid,
  1784         noteeid = self.execute('INSERT Note X')[0][0]
  1760         noteeid = self.execute('INSERT Note X')[0][0]
  1785         self._test('DISTINCT Card V WHERE MB documented_by MV, MV eid %(x)s, '
  1761         self._test('DISTINCT Card V WHERE MB documented_by MV, MV eid %(x)s, '
  1786                    'MB depends_on B, B documented_by V, V multisource_rel P, NOT P eid %(p)s',
  1762                    'MB depends_on B, B documented_by V, V multisource_rel P, NOT P eid %(p)s',
  1787                    [('FetchStep', [('Any V WHERE V multisource_rel P, NOT P eid %s, P is Note, V is Card'%noteeid,
  1763                    [('FetchStep', [('Any V WHERE V multisource_rel P, NOT P eid %s, P is Note, V is Card'%noteeid,
  1788                                     [{'P': 'Note', 'V': 'Card'}])],
  1764                                     [{'P': 'Note', 'V': 'Card'}])],
  1789                      [self.rql, self.system], None, {'V': 'table0.C0'}, []),
  1765                      [self.cards, self.system], None, {'V': 'table0.C0'}, []),
  1790                     ('OneFetchStep', [('DISTINCT Any V WHERE MB documented_by %s, MB depends_on B, B documented_by V, B is Affaire, MB is Affaire, V is Card'%cardeid,
  1766                     ('OneFetchStep', [('DISTINCT Any V WHERE MB documented_by %s, MB depends_on B, B documented_by V, B is Affaire, MB is Affaire, V is Card'%cardeid,
  1791                                        [{'B': 'Affaire', 'MB': 'Affaire', 'V': 'Card'}])],
  1767                                        [{'B': 'Affaire', 'MB': 'Affaire', 'V': 'Card'}])],
  1792                      None, None, [self.system], {'V': 'table0.C0'}, [])],
  1768                      None, None, [self.system], {'V': 'table0.C0'}, [])],
  1793                    {'x': cardeid, 'p': noteeid})
  1769                    {'x': cardeid, 'p': noteeid})
  1794 
  1770 
  1802                                         {'Y': 'Affaire', 'X': 'Personne'}])],
  1778                                         {'Y': 'Affaire', 'X': 'Personne'}])],
  1803                      None,  None, [self.system], {}, [])
  1779                      None,  None, [self.system], {}, [])
  1804                     ])
  1780                     ])
  1805         self._test('Any X WHERE X concerne Y, Y is Note',
  1781         self._test('Any X WHERE X concerne Y, Y is Note',
  1806                    [('FetchStep', [('Any Y WHERE Y is Note', [{'Y': 'Note'}])],
  1782                    [('FetchStep', [('Any Y WHERE Y is Note', [{'Y': 'Note'}])],
  1807                       [self.rql, self.system], None, {'Y': 'table0.C0'}, []),
  1783                       [self.cards, self.system], None, {'Y': 'table0.C0'}, []),
  1808                     ('OneFetchStep', [('Any X WHERE X concerne Y, X is Affaire, Y is Note',
  1784                     ('OneFetchStep', [('Any X WHERE X concerne Y, X is Affaire, Y is Note',
  1809                                        [{'X': 'Affaire', 'Y': 'Note'}])],
  1785                                        [{'X': 'Affaire', 'Y': 'Note'}])],
  1810                      None, None, [self.system], {'Y': 'table0.C0'}, [])
  1786                      None, None, [self.system], {'Y': 'table0.C0'}, [])
  1811                     ])
  1787                     ])
  1812 
  1788 
  1813     def test_nonregr7(self):
  1789     def test_nonregr7(self):
  1814         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1790         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1815         self._test('Any S,SUM(DUR),SUM(I),(SUM(I) - SUM(DUR)),MIN(DI),MAX(DI) GROUPBY S ORDERBY S WHERE A is Affaire, A duration DUR, A invoiced I, A modification_date DI, A in_state S, S name SN, (EXISTS(A concerne WP, W multisource_rel WP)) OR (EXISTS(A concerne W)), W eid %(n)s',
  1791         self._test('Any S,SUM(DUR),SUM(I),(SUM(I) - SUM(DUR)),MIN(DI),MAX(DI) GROUPBY S ORDERBY S WHERE A is Affaire, A duration DUR, A invoiced I, A modification_date DI, A in_state S, S name SN, (EXISTS(A concerne WP, W multisource_rel WP)) OR (EXISTS(A concerne W)), W eid %(n)s',
  1816                    [('FetchStep', [('Any WP WHERE 999999 multisource_rel WP, WP is Note', [{'WP': 'Note'}])],
  1792                    [('FetchStep', [('Any WP WHERE 999999 multisource_rel WP, WP is Note', [{'WP': 'Note'}])],
  1817                      [self.rql], None, {'WP': u'table0.C0'}, []),
  1793                      [self.cards], None, {'WP': u'table0.C0'}, []),
  1818                     ('OneFetchStep', [('Any S,SUM(DUR),SUM(I),(SUM(I) - SUM(DUR)),MIN(DI),MAX(DI) GROUPBY S ORDERBY S WHERE A duration DUR, A invoiced I, A modification_date DI, A in_state S, S name SN, (EXISTS(A concerne WP, WP is Note)) OR (EXISTS(A concerne 999999)), A is Affaire, S is State',
  1794                     ('OneFetchStep', [('Any S,SUM(DUR),SUM(I),(SUM(I) - SUM(DUR)),MIN(DI),MAX(DI) GROUPBY S ORDERBY S WHERE A duration DUR, A invoiced I, A modification_date DI, A in_state S, S name SN, (EXISTS(A concerne WP, WP is Note)) OR (EXISTS(A concerne 999999)), A is Affaire, S is State',
  1819                                        [{'A': 'Affaire', 'DI': 'Datetime', 'DUR': 'Int', 'I': 'Int', 'S': 'State', 'SN': 'String', 'WP': 'Note'}])],
  1795                                        [{'A': 'Affaire', 'DI': 'Datetime', 'DUR': 'Int', 'I': 'Int', 'S': 'State', 'SN': 'String', 'WP': 'Note'}])],
  1820                      None, None, [self.system], {'WP': u'table0.C0'}, [])],
  1796                      None, None, [self.system], {'WP': u'table0.C0'}, [])],
  1821                    {'n': 999999})
  1797                    {'n': 999999})
  1822 
  1798 
  1823     def test_nonregr8(self):
  1799     def test_nonregr8(self):
  1824         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1800         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1825         self._test('Any X,Z WHERE X eid %(x)s, X multisource_rel Y, Z concerne X',
  1801         self._test('Any X,Z WHERE X eid %(x)s, X multisource_rel Y, Z concerne X',
  1826                    [('FetchStep', [('Any  WHERE 999999 multisource_rel Y, Y is Note', [{'Y': 'Note'}])],
  1802                    [('FetchStep', [('Any  WHERE 999999 multisource_rel Y, Y is Note', [{'Y': 'Note'}])],
  1827                      [self.rql], None, {}, []),
  1803                      [self.cards], None, {}, []),
  1828                     ('OneFetchStep', [('Any 999999,Z WHERE Z concerne 999999, Z is Affaire',
  1804                     ('OneFetchStep', [('Any 999999,Z WHERE Z concerne 999999, Z is Affaire',
  1829                                        [{'Z': 'Affaire'}])],
  1805                                        [{'Z': 'Affaire'}])],
  1830                      None, None, [self.system], {}, [])],
  1806                      None, None, [self.system], {}, [])],
  1831                    {'x': 999999})
  1807                    {'x': 999999})
  1832 
  1808 
  1833     def test_nonregr9(self):
  1809     def test_nonregr9(self):
  1834         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1810         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1835         repo._type_source_cache[999998] = ('Note', 'cards', 999998)
  1811         repo._type_source_cache[999998] = ('Note', 'cards', 999998)
  1836         self._test('SET X migrated_from Y WHERE X eid %(x)s, Y multisource_rel Z, Z eid %(z)s, Y migrated_from Z',
  1812         self._test('SET X migrated_from Y WHERE X eid %(x)s, Y multisource_rel Z, Z eid %(z)s, Y migrated_from Z',
  1837                    [('FetchStep', [('Any Y WHERE Y multisource_rel 999998, Y is Note', [{'Y': 'Note'}])],
  1813                    [('FetchStep', [('Any Y WHERE Y multisource_rel 999998, Y is Note', [{'Y': 'Note'}])],
  1838                      [self.rql], None, {'Y': u'table0.C0'}, []),
  1814                      [self.cards], None, {'Y': u'table0.C0'}, []),
  1839                     ('UpdateStep',
  1815                     ('UpdateStep',
  1840                      [('OneFetchStep', [('DISTINCT Any 999999,Y WHERE Y migrated_from 999998, Y is Note',
  1816                      [('OneFetchStep', [('DISTINCT Any 999999,Y WHERE Y migrated_from 999998, Y is Note',
  1841                                          [{'Y': 'Note'}])],
  1817                                          [{'Y': 'Note'}])],
  1842                        None, None, [self.system],
  1818                        None, None, [self.system],
  1843                        {'Y': u'table0.C0'}, [])])],
  1819                        {'Y': u'table0.C0'}, [])])],
  1844                    {'x': 999999, 'z': 999998})
  1820                    {'x': 999999, 'z': 999998})
  1845 
  1821 
  1846     def test_nonregr10(self):
  1822     def test_nonregr10(self):
  1847         repo._type_source_cache[999999] = ('CWUser', 'ldapuser', 999999)
  1823         repo._type_source_cache[999999] = ('CWUser', 'ldap', 999999)
  1848         self._test('Any X,AA,AB ORDERBY AA WHERE E eid %(x)s, E owned_by X, X login AA, X modification_date AB',
  1824         self._test('Any X,AA,AB ORDERBY AA WHERE E eid %(x)s, E owned_by X, X login AA, X modification_date AB',
  1849                    [('FetchStep',
  1825                    [('FetchStep',
  1850                      [('Any X,AA,AB WHERE X login AA, X modification_date AB, X is CWUser',
  1826                      [('Any X,AA,AB WHERE X login AA, X modification_date AB, X is CWUser',
  1851                        [{'AA': 'String', 'AB': 'Datetime', 'X': 'CWUser'}])],
  1827                        [{'AA': 'String', 'AB': 'Datetime', 'X': 'CWUser'}])],
  1852                      [self.ldap, self.system], None, {'AA': 'table0.C1', 'AB': 'table0.C2',
  1828                      [self.ldap, self.system], None, {'AA': 'table0.C1', 'AB': 'table0.C2',
  1878     def test_nonregr12(self):
  1854     def test_nonregr12(self):
  1879         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1855         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1880         self._test('Any X ORDERBY Z DESC WHERE X modification_date Z, E eid %(x)s, E see_also X',
  1856         self._test('Any X ORDERBY Z DESC WHERE X modification_date Z, E eid %(x)s, E see_also X',
  1881                    [('FetchStep', [('Any X,Z WHERE X modification_date Z, X is Note',
  1857                    [('FetchStep', [('Any X,Z WHERE X modification_date Z, X is Note',
  1882                                     [{'X': 'Note', 'Z': 'Datetime'}])],
  1858                                     [{'X': 'Note', 'Z': 'Datetime'}])],
  1883                      [self.rql, self.system], None, {'X': 'table0.C0', 'X.modification_date': 'table0.C1', 'Z': 'table0.C1'},
  1859                      [self.cards, self.system], None, {'X': 'table0.C0', 'X.modification_date': 'table0.C1', 'Z': 'table0.C1'},
  1884                      []),
  1860                      []),
  1885                     ('AggrStep', 'Any X ORDERBY Z DESC',
  1861                     ('AggrStep', 'Any X ORDERBY Z DESC',
  1886                      None, None, 'table1', None,
  1862                      None, None, 'table1', None,
  1887                      [('FetchStep', [('Any X,Z WHERE X modification_date Z, 999999 see_also X, X is Bookmark',
  1863                      [('FetchStep', [('Any X,Z WHERE X modification_date Z, 999999 see_also X, X is Bookmark',
  1888                                       [{'X': 'Bookmark', 'Z': 'Datetime'}])],
  1864                                       [{'X': 'Bookmark', 'Z': 'Datetime'}])],
  1965     * 2 rql sources supporting Card
  1941     * 2 rql sources supporting Card
  1966     """
  1942     """
  1967     repo = repo
  1943     repo = repo
  1968 
  1944 
  1969     def setUp(self):
  1945     def setUp(self):
  1970         self.o = repo.querier
  1946         self.setup()
  1971         self.session = repo._sessions.values()[0]
  1947         self.add_source(FakeCardSource, 'cards')
  1972         self.pool = self.session.set_pool()
  1948         self.add_source(FakeCardSource, 'cards2')
  1973         self.schema = self.o.schema
       
  1974         self.sources = self.o._repo.sources
       
  1975         self.system = self.sources[-1]
       
  1976         self.sources.append(FakeCardSource(self.o._repo, self.o.schema,
       
  1977                                            {'uri': 'cards'}))
       
  1978         repo.sources_by_uri['cards'] = self.sources[-1]
       
  1979         self.rql = self.sources[-1]
       
  1980         self.sources.append(FakeCardSource(self.o._repo, self.o.schema,
       
  1981                                            {'uri': 'cards2'}))
       
  1982         repo.sources_by_uri['cards2'] = self.sources[-1]
       
  1983         self.rql2 = self.sources[-1]
       
  1984         do_monkey_patch()
       
  1985         self.planner = MSPlanner(self.o.schema, self.o._rqlhelper)
  1949         self.planner = MSPlanner(self.o.schema, self.o._rqlhelper)
  1986         assert repo.sources_by_uri['cards2'].support_relation('multisource_crossed_rel')
  1950         assert repo.sources_by_uri['cards2'].support_relation('multisource_crossed_rel')
  1987         assert 'multisource_crossed_rel' in repo.sources_by_uri['cards2'].cross_relations
  1951         assert 'multisource_crossed_rel' in repo.sources_by_uri['cards2'].cross_relations
  1988         assert repo.sources_by_uri['cards'].support_relation('multisource_crossed_rel')
  1952         assert repo.sources_by_uri['cards'].support_relation('multisource_crossed_rel')
  1989         assert 'multisource_crossed_rel' in repo.sources_by_uri['cards'].cross_relations
  1953         assert 'multisource_crossed_rel' in repo.sources_by_uri['cards'].cross_relations
  1990         clear_ms_caches(repo)
       
  1991     _test = test_plan
  1954     _test = test_plan
  1992 
  1955 
  1993     def tearDown(self):
       
  1994         undo_monkey_patch()
       
  1995         del self.sources[-1]
       
  1996         del self.sources[-1]
       
  1997         del repo.sources_by_uri['cards']
       
  1998         del repo.sources_by_uri['cards2']
       
  1999 
  1956 
  2000     def test_linked_external_entities(self):
  1957     def test_linked_external_entities(self):
  2001         repo._type_source_cache[999999] = ('Tag', 'system', 999999)
  1958         repo._type_source_cache[999999] = ('Tag', 'system', 999999)
  2002         self._test('Any X,XT WHERE X is Card, X title XT, T tags X, T eid %(t)s',
  1959         self._test('Any X,XT WHERE X is Card, X title XT, T tags X, T eid %(t)s',
  2003                    [('FetchStep',
  1960                    [('FetchStep',
  2004                      [('Any X,XT WHERE X title XT, X is Card', [{'X': 'Card', 'XT': 'String'}])],
  1961                      [('Any X,XT WHERE X title XT, X is Card', [{'X': 'Card', 'XT': 'String'}])],
  2005                      [self.rql, self.rql2, self.system],
  1962                      [self.cards, self.cards2, self.system],
  2006                      None, {'X': 'table0.C0', 'X.title': 'table0.C1', 'XT': 'table0.C1'},
  1963                      None, {'X': 'table0.C0', 'X.title': 'table0.C1', 'XT': 'table0.C1'},
  2007                      []),
  1964                      []),
  2008                     ('OneFetchStep',
  1965                     ('OneFetchStep',
  2009                      [('Any X,XT WHERE X title XT, 999999 tags X, X is Card',
  1966                      [('Any X,XT WHERE X title XT, 999999 tags X, X is Card',
  2010                        [{'X': 'Card', 'XT': 'String'}])],
  1967                        [{'X': 'Card', 'XT': 'String'}])],
  2016     def test_version_depends_on(self):
  1973     def test_version_depends_on(self):
  2017         self.repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1974         self.repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  2018         self._test('Any X,AD,AE WHERE E eid %(x)s, E migrated_from X, X in_state AD, AD name AE',
  1975         self._test('Any X,AD,AE WHERE E eid %(x)s, E migrated_from X, X in_state AD, AD name AE',
  2019                    [('FetchStep', [('Any X,AD,AE WHERE X in_state AD, AD name AE, AD is State, X is Note',
  1976                    [('FetchStep', [('Any X,AD,AE WHERE X in_state AD, AD name AE, AD is State, X is Note',
  2020                                     [{'AD': 'State', 'AE': 'String', 'X': 'Note'}])],
  1977                                     [{'AD': 'State', 'AE': 'String', 'X': 'Note'}])],
  2021                      [self.rql, self.rql2, self.system],
  1978                      [self.cards, self.cards2, self.system],
  2022                      None, {'AD': 'table0.C1', 'AD.name': 'table0.C2',
  1979                      None, {'AD': 'table0.C1', 'AD.name': 'table0.C2',
  2023                             'AE': 'table0.C2', 'X': 'table0.C0'},
  1980                             'AE': 'table0.C2', 'X': 'table0.C0'},
  2024                      []),
  1981                      []),
  2025                     ('OneFetchStep', [('Any X,AD,AE WHERE 999999 migrated_from X, AD name AE, AD is State, X is Note',
  1982                     ('OneFetchStep', [('Any X,AD,AE WHERE 999999 migrated_from X, AD name AE, AD is State, X is Note',
  2026                                        [{'AD': 'State', 'AE': 'String', 'X': 'Note'}])],
  1983                                        [{'AD': 'State', 'AE': 'String', 'X': 'Note'}])],
  2032     def test_version_crossed_depends_on_1(self):
  1989     def test_version_crossed_depends_on_1(self):
  2033         self.repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1990         self.repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  2034         self._test('Any X,AD,AE WHERE E eid %(x)s, E multisource_crossed_rel X, X in_state AD, AD name AE',
  1991         self._test('Any X,AD,AE WHERE E eid %(x)s, E multisource_crossed_rel X, X in_state AD, AD name AE',
  2035                    [('FetchStep', [('Any X,AD,AE WHERE X in_state AD, AD name AE, AD is State, X is Note',
  1992                    [('FetchStep', [('Any X,AD,AE WHERE X in_state AD, AD name AE, AD is State, X is Note',
  2036                                     [{'AD': 'State', 'AE': 'String', 'X': 'Note'}])],
  1993                                     [{'AD': 'State', 'AE': 'String', 'X': 'Note'}])],
  2037                      [self.rql, self.rql2, self.system],
  1994                      [self.cards, self.cards2, self.system],
  2038                      None, {'AD': 'table0.C1', 'AD.name': 'table0.C2',
  1995                      None, {'AD': 'table0.C1', 'AD.name': 'table0.C2',
  2039                             'AE': 'table0.C2', 'X': 'table0.C0'},
  1996                             'AE': 'table0.C2', 'X': 'table0.C0'},
  2040                      []),
  1997                      []),
  2041                     ('UnionStep', None, None,
  1998                     ('UnionStep', None, None,
  2042                      [('OneFetchStep', [('Any X,AD,AE WHERE 999999 multisource_crossed_rel X, AD name AE, AD is State, X is Note',
  1999                      [('OneFetchStep', [('Any X,AD,AE WHERE 999999 multisource_crossed_rel X, AD name AE, AD is State, X is Note',
  2043                                          [{'AD': 'State', 'AE': 'String', 'X': 'Note'}])],
  2000                                          [{'AD': 'State', 'AE': 'String', 'X': 'Note'}])],
  2044                        None, None, [self.rql], None,
  2001                        None, None, [self.cards], None,
  2045                        []),
  2002                        []),
  2046                       ('OneFetchStep', [('Any X,AD,AE WHERE 999999 multisource_crossed_rel X, AD name AE, AD is State, X is Note',
  2003                       ('OneFetchStep', [('Any X,AD,AE WHERE 999999 multisource_crossed_rel X, AD name AE, AD is State, X is Note',
  2047                                          [{'AD': 'State', 'AE': 'String', 'X': 'Note'}])],
  2004                                          [{'AD': 'State', 'AE': 'String', 'X': 'Note'}])],
  2048                        None, None, [self.system],
  2005                        None, None, [self.system],
  2049                        {'AD': 'table0.C1', 'AD.name': 'table0.C2',
  2006                        {'AD': 'table0.C1', 'AD.name': 'table0.C2',
  2055     def test_version_crossed_depends_on_2(self):
  2012     def test_version_crossed_depends_on_2(self):
  2056         self.repo._type_source_cache[999999] = ('Note', 'system', 999999)
  2013         self.repo._type_source_cache[999999] = ('Note', 'system', 999999)
  2057         self._test('Any X,AD,AE WHERE E eid %(x)s, E multisource_crossed_rel X, X in_state AD, AD name AE',
  2014         self._test('Any X,AD,AE WHERE E eid %(x)s, E multisource_crossed_rel X, X in_state AD, AD name AE',
  2058                    [('FetchStep', [('Any X,AD,AE WHERE X in_state AD, AD name AE, AD is State, X is Note',
  2015                    [('FetchStep', [('Any X,AD,AE WHERE X in_state AD, AD name AE, AD is State, X is Note',
  2059                                     [{'AD': 'State', 'AE': 'String', 'X': 'Note'}])],
  2016                                     [{'AD': 'State', 'AE': 'String', 'X': 'Note'}])],
  2060                      [self.rql, self.rql2, self.system],
  2017                      [self.cards, self.cards2, self.system],
  2061                      None, {'AD': 'table0.C1', 'AD.name': 'table0.C2',
  2018                      None, {'AD': 'table0.C1', 'AD.name': 'table0.C2',
  2062                             'AE': 'table0.C2', 'X': 'table0.C0'},
  2019                             'AE': 'table0.C2', 'X': 'table0.C0'},
  2063                      []),
  2020                      []),
  2064                     ('OneFetchStep', [('Any X,AD,AE WHERE 999999 multisource_crossed_rel X, AD name AE, AD is State, X is Note',
  2021                     ('OneFetchStep', [('Any X,AD,AE WHERE 999999 multisource_crossed_rel X, AD name AE, AD is State, X is Note',
  2065                                        [{'AD': 'State', 'AE': 'String', 'X': 'Note'}])],
  2022                                        [{'AD': 'State', 'AE': 'String', 'X': 'Note'}])],
  2070 
  2027 
  2071     def test_version_crossed_depends_on_3(self):
  2028     def test_version_crossed_depends_on_3(self):
  2072         self._test('Any X,AD,AE WHERE E multisource_crossed_rel X, X in_state AD, AD name AE, E is Note',
  2029         self._test('Any X,AD,AE WHERE E multisource_crossed_rel X, X in_state AD, AD name AE, E is Note',
  2073                    [('FetchStep', [('Any X,AD,AE WHERE X in_state AD, AD name AE, AD is State, X is Note',
  2030                    [('FetchStep', [('Any X,AD,AE WHERE X in_state AD, AD name AE, AD is State, X is Note',
  2074                                     [{'AD': 'State', 'AE': 'String', 'X': 'Note'}])],
  2031                                     [{'AD': 'State', 'AE': 'String', 'X': 'Note'}])],
  2075                      [self.rql, self.rql2, self.system],
  2032                      [self.cards, self.cards2, self.system],
  2076                      None, {'AD': 'table0.C1', 'AD.name': 'table0.C2',
  2033                      None, {'AD': 'table0.C1', 'AD.name': 'table0.C2',
  2077                             'AE': 'table0.C2', 'X': 'table0.C0'},
  2034                             'AE': 'table0.C2', 'X': 'table0.C0'},
  2078                      []),
  2035                      []),
  2079                     ('FetchStep', [('Any E WHERE E is Note', [{'E': 'Note'}])],
  2036                     ('FetchStep', [('Any E WHERE E is Note', [{'E': 'Note'}])],
  2080                      [self.rql, self.rql2, self.system],
  2037                      [self.cards, self.cards2, self.system],
  2081                      None, {'E': 'table1.C0'},
  2038                      None, {'E': 'table1.C0'},
  2082                      []),
  2039                      []),
  2083                     ('UnionStep', None, None,
  2040                     ('UnionStep', None, None,
  2084                      [('OneFetchStep', [('Any X,AD,AE WHERE E multisource_crossed_rel X, AD name AE, AD is State, E is Note, X is Note',
  2041                      [('OneFetchStep', [('Any X,AD,AE WHERE E multisource_crossed_rel X, AD name AE, AD is State, E is Note, X is Note',
  2085                                          [{'AD': 'State', 'AE': 'String', 'E': 'Note', 'X': 'Note'}])],
  2042                                          [{'AD': 'State', 'AE': 'String', 'E': 'Note', 'X': 'Note'}])],
  2086                        None, None, [self.rql, self.rql2], None,
  2043                        None, None, [self.cards, self.cards2], None,
  2087                        []),
  2044                        []),
  2088                       ('OneFetchStep', [('Any X,AD,AE WHERE E multisource_crossed_rel X, AD name AE, AD is State, E is Note, X is Note',
  2045                       ('OneFetchStep', [('Any X,AD,AE WHERE E multisource_crossed_rel X, AD name AE, AD is State, E is Note, X is Note',
  2089                                          [{'AD': 'State', 'AE': 'String', 'E': 'Note', 'X': 'Note'}])],
  2046                                          [{'AD': 'State', 'AE': 'String', 'E': 'Note', 'X': 'Note'}])],
  2090                        None, None, [self.system],
  2047                        None, None, [self.system],
  2091                        {'AD': 'table0.C1',
  2048                        {'AD': 'table0.C1',
  2100     def test_nonregr_dont_cross_rel_source_filtering_1(self):
  2057     def test_nonregr_dont_cross_rel_source_filtering_1(self):
  2101         self.repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  2058         self.repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  2102         self._test('Any S WHERE E eid %(x)s, E in_state S, NOT S name "moved"',
  2059         self._test('Any S WHERE E eid %(x)s, E in_state S, NOT S name "moved"',
  2103                    [('OneFetchStep', [('Any S WHERE 999999 in_state S, NOT S name "moved", S is State',
  2060                    [('OneFetchStep', [('Any S WHERE 999999 in_state S, NOT S name "moved", S is State',
  2104                                        [{'S': 'State'}])],
  2061                                        [{'S': 'State'}])],
  2105                      None, None, [self.rql], {}, []
  2062                      None, None, [self.cards], {}, []
  2106                      )],
  2063                      )],
  2107                    {'x': 999999})
  2064                    {'x': 999999})
  2108 
  2065 
  2109     def test_nonregr_dont_cross_rel_source_filtering_2(self):
  2066     def test_nonregr_dont_cross_rel_source_filtering_2(self):
  2110         self.repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  2067         self.repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  2111         self._test('Any X,AA,AB WHERE E eid %(x)s, E in_state X, X name AA, X modification_date AB',
  2068         self._test('Any X,AA,AB WHERE E eid %(x)s, E in_state X, X name AA, X modification_date AB',
  2112                    [('OneFetchStep', [('Any X,AA,AB WHERE 999999 in_state X, X name AA, X modification_date AB, X is State',
  2069                    [('OneFetchStep', [('Any X,AA,AB WHERE 999999 in_state X, X name AA, X modification_date AB, X is State',
  2113                                        [{'AA': 'String', 'AB': 'Datetime', 'X': 'State'}])],
  2070                                        [{'AA': 'String', 'AB': 'Datetime', 'X': 'State'}])],
  2114                      None, None, [self.rql], {}, []
  2071                      None, None, [self.cards], {}, []
  2115                      )],
  2072                      )],
  2116                    {'x': 999999})
  2073                    {'x': 999999})
  2117 
  2074 
  2118 
  2075 
  2119 if __name__ == '__main__':
  2076 if __name__ == '__main__':