22 support_entities = {'CWUser': False} |
22 support_entities = {'CWUser': False} |
23 support_relations = {} |
23 support_relations = {} |
24 def syntax_tree_search(self, *args, **kwargs): |
24 def syntax_tree_search(self, *args, **kwargs): |
25 return [] |
25 return [] |
26 |
26 |
27 |
27 |
28 class FakeCardSource(AbstractSource): |
28 class FakeCardSource(AbstractSource): |
29 uri = 'ccc' |
29 uri = 'ccc' |
30 support_entities = {'Card': True, 'Note': True, 'State': True} |
30 support_entities = {'Card': True, 'Note': True, 'State': True} |
31 support_relations = {'in_state': True, 'multisource_rel': True, 'multisource_inlined_rel': True, |
31 support_relations = {'in_state': True, 'multisource_rel': True, 'multisource_inlined_rel': True, |
32 'multisource_crossed_rel': True} |
32 'multisource_crossed_rel': True} |
33 dont_cross_relations = set(('fiche',)) |
33 dont_cross_relations = set(('fiche', 'in_state')) |
34 cross_relations = set(('multisource_crossed_rel',)) |
34 cross_relations = set(('multisource_crossed_rel',)) |
35 |
35 |
36 def syntax_tree_search(self, *args, **kwargs): |
36 def syntax_tree_search(self, *args, **kwargs): |
37 return [] |
37 return [] |
38 |
38 |
39 X_ALL_SOLS = sorted([{'X': 'Affaire'}, {'X': 'Basket'}, {'X': 'Bookmark'}, |
39 X_ALL_SOLS = sorted([{'X': 'Affaire'}, {'X': 'Basket'}, {'X': 'Bookmark'}, |
40 {'X': 'Card'}, {'X': 'Comment'}, {'X': 'Division'}, |
40 {'X': 'Card'}, {'X': 'Comment'}, {'X': 'Division'}, |
51 def clear_ms_caches(repo): |
51 def clear_ms_caches(repo): |
52 clear_cache(repo, 'rel_type_sources') |
52 clear_cache(repo, 'rel_type_sources') |
53 clear_cache(repo, 'can_cross_relation') |
53 clear_cache(repo, 'can_cross_relation') |
54 clear_cache(repo, 'is_multi_sources_relation') |
54 clear_cache(repo, 'is_multi_sources_relation') |
55 # XXX source_defs |
55 # XXX source_defs |
56 |
56 |
57 # keep cnx so it's not garbage collected and the associated session is closed |
57 # keep cnx so it's not garbage collected and the associated session is closed |
58 repo, cnx = init_test_database('sqlite') |
58 repo, cnx = init_test_database('sqlite') |
59 |
59 |
60 class BaseMSPlannerTC(BasePlannerTC): |
60 class BaseMSPlannerTC(BasePlannerTC): |
61 """test planner related feature on a 3-sources repository: |
61 """test planner related feature on a 3-sources repository: |
62 |
62 |
63 * system source supporting everything |
63 * system source supporting everything |
64 * ldap source supporting CWUser |
64 * ldap source supporting CWUser |
65 * rql source supporting Card |
65 * rql source supporting Card |
66 """ |
66 """ |
67 repo = repo |
67 repo = repo |
68 |
68 |
69 def setUp(self): |
69 def setUp(self): |
70 #_QuerierTC.setUp(self) |
70 #_QuerierTC.setUp(self) |
71 clear_cache(repo, 'rel_type_sources') |
71 clear_cache(repo, 'rel_type_sources') |
72 self.o = repo.querier |
72 self.o = repo.querier |
73 self.session = repo._sessions.values()[0] |
73 self.session = repo._sessions.values()[0] |
95 {'uri': 'cards'})) |
95 {'uri': 'cards'})) |
96 repo.sources_by_uri['cards'] = self.sources[-1] |
96 repo.sources_by_uri['cards'] = self.sources[-1] |
97 self.rql = self.sources[-1] |
97 self.rql = self.sources[-1] |
98 do_monkey_patch() |
98 do_monkey_patch() |
99 clear_ms_caches(repo) |
99 clear_ms_caches(repo) |
100 |
100 |
101 def tearDown(self): |
101 def tearDown(self): |
102 undo_monkey_patch() |
102 undo_monkey_patch() |
103 del self.sources[-1] |
103 del self.sources[-1] |
104 del self.sources[-1] |
104 del self.sources[-1] |
105 del repo.sources_by_uri['ldapuser'] |
105 del repo.sources_by_uri['ldapuser'] |
106 del repo.sources_by_uri['cards'] |
106 del repo.sources_by_uri['cards'] |
107 # restore hijacked security |
107 # restore hijacked security |
108 self.restore_orig_affaire_security() |
108 self.restore_orig_affaire_security() |
109 self.restore_orig_euser_security() |
109 self.restore_orig_euser_security() |
110 |
110 |
111 def restore_orig_affaire_security(self): |
111 def restore_orig_affaire_security(self): |
112 affreadperms = list(self.schema['Affaire']._groups['read']) |
112 affreadperms = list(self.schema['Affaire']._groups['read']) |
113 affreadperms[-1] = self.prevrqlexpr_affaire |
113 affreadperms[-1] = self.prevrqlexpr_affaire |
114 self.schema['Affaire']._groups['read'] = tuple(affreadperms) |
114 self.schema['Affaire']._groups['read'] = tuple(affreadperms) |
115 clear_cache(self.schema['Affaire'], 'ERSchema_get_rqlexprs') |
115 clear_cache(self.schema['Affaire'], 'ERSchema_get_rqlexprs') |
116 |
116 |
117 def restore_orig_euser_security(self): |
117 def restore_orig_euser_security(self): |
118 userreadperms = list(self.schema['CWUser']._groups['read']) |
118 userreadperms = list(self.schema['CWUser']._groups['read']) |
119 userreadperms[-1] = self.prevrqlexpr_user |
119 userreadperms[-1] = self.prevrqlexpr_user |
120 self.schema['CWUser']._groups['read'] = tuple(userreadperms) |
120 self.schema['CWUser']._groups['read'] = tuple(userreadperms) |
121 clear_cache(self.schema['CWUser'], 'ERSchema_get_rqlexprs') |
121 clear_cache(self.schema['CWUser'], 'ERSchema_get_rqlexprs') |
122 |
122 |
123 |
123 |
124 class PartPlanInformationTC(BaseMSPlannerTC): |
124 class PartPlanInformationTC(BaseMSPlannerTC): |
125 |
125 |
126 def _test(self, rql, *args): |
126 def _test(self, rql, *args): |
127 if len(args) == 3: |
127 if len(args) == 3: |
128 kwargs, sourcesterms, needsplit = args |
128 kwargs, sourcesterms, needsplit = args |
138 solindices = sourcevars.pop(var) |
138 solindices = sourcevars.pop(var) |
139 sourcevars[var._ms_table_key()] = solindices |
139 sourcevars[var._ms_table_key()] = solindices |
140 self.assertEquals(ppi._sourcesterms, sourcesterms) |
140 self.assertEquals(ppi._sourcesterms, sourcesterms) |
141 self.assertEquals(ppi.needsplit, needsplit) |
141 self.assertEquals(ppi.needsplit, needsplit) |
142 |
142 |
143 |
143 |
144 def test_simple_system_only(self): |
144 def test_simple_system_only(self): |
145 """retrieve entities only supported by the system source""" |
145 """retrieve entities only supported by the system source""" |
146 self._test('CWGroup X', |
146 self._test('CWGroup X', |
147 {self.system: {'X': s[0]}}, False) |
147 {self.system: {'X': s[0]}}, False) |
148 |
148 |
149 def test_simple_system_ldap(self): |
149 def test_simple_system_ldap(self): |
150 """retrieve CWUser X from both sources and return concatenation of results |
150 """retrieve CWUser X from both sources and return concatenation of results |
151 """ |
151 """ |
152 self._test('CWUser X', |
152 self._test('CWUser X', |
153 {self.system: {'X': s[0]}, self.ldap: {'X': s[0]}}, False) |
153 {self.system: {'X': s[0]}, self.ldap: {'X': s[0]}}, False) |
154 |
154 |
155 def test_simple_system_rql(self): |
155 def test_simple_system_rql(self): |
156 """retrieve Card X from both sources and return concatenation of results |
156 """retrieve Card X from both sources and return concatenation of results |
157 """ |
157 """ |
158 self._test('Any X, XT WHERE X is Card, X title XT', |
158 self._test('Any X, XT WHERE X is Card, X title XT', |
159 {self.system: {'X': s[0]}, self.rql: {'X': s[0]}}, False) |
159 {self.system: {'X': s[0]}, self.rql: {'X': s[0]}}, False) |
160 |
160 |
161 def test_simple_eid_specified(self): |
161 def test_simple_eid_specified(self): |
162 """retrieve CWUser X from system source (eid is specified, can locate the entity) |
162 """retrieve CWUser X from system source (eid is specified, can locate the entity) |
163 """ |
163 """ |
164 ueid = self.session.user.eid |
164 ueid = self.session.user.eid |
165 self._test('Any X,L WHERE X eid %(x)s, X login L', {'x': ueid}, |
165 self._test('Any X,L WHERE X eid %(x)s, X login L', {'x': ueid}, |
166 {self.system: {'X': s[0]}}, False) |
166 {self.system: {'X': s[0]}}, False) |
167 |
167 |
168 def test_simple_eid_invariant(self): |
168 def test_simple_eid_invariant(self): |
169 """retrieve CWUser X from system source (eid is specified, can locate the entity) |
169 """retrieve CWUser X from system source (eid is specified, can locate the entity) |
170 """ |
170 """ |
171 ueid = self.session.user.eid |
171 ueid = self.session.user.eid |
172 self._test('Any X WHERE X eid %(x)s', {'x': ueid}, |
172 self._test('Any X WHERE X eid %(x)s', {'x': ueid}, |
173 {self.system: {'x': s[0]}}, False) |
173 {self.system: {'x': s[0]}}, False) |
174 |
174 |
175 def test_simple_invariant(self): |
175 def test_simple_invariant(self): |
176 """retrieve CWUser X from system source only (X is invariant and in_group not supported by ldap source) |
176 """retrieve CWUser X from system source only (X is invariant and in_group not supported by ldap source) |
177 """ |
177 """ |
178 self._test('Any X WHERE X is CWUser, X in_group G, G name "users"', |
178 self._test('Any X WHERE X is CWUser, X in_group G, G name "users"', |
179 {self.system: {'X': s[0], 'G': s[0], 'in_group': s[0]}}, False) |
179 {self.system: {'X': s[0], 'G': s[0], 'in_group': s[0]}}, False) |
180 |
180 |
181 def test_security_has_text(self): |
181 def test_security_has_text(self): |
182 """retrieve CWUser X from system source only (has_text not supported by ldap source) |
182 """retrieve CWUser X from system source only (has_text not supported by ldap source) |
183 """ |
183 """ |
184 # specify CWUser instead of any since the way this test is written we aren't well dealing |
184 # specify CWUser instead of any since the way this test is written we aren't well dealing |
185 # with ambigous query (eg only considering the first solution) |
185 # with ambigous query (eg only considering the first solution) |
186 self._test('CWUser X WHERE X has_text "bla"', |
186 self._test('CWUser X WHERE X has_text "bla"', |
187 {self.system: {'X': s[0]}}, False) |
187 {self.system: {'X': s[0]}}, False) |
188 |
188 |
189 def test_complex_base(self): |
189 def test_complex_base(self): |
190 """ |
190 """ |
191 1. retrieve Any X, L WHERE X is CWUser, X login L from system and ldap sources, store |
191 1. retrieve Any X, L WHERE X is CWUser, X login L from system and ldap sources, store |
192 concatenation of results into a temporary table |
192 concatenation of results into a temporary table |
193 2. return the result of Any X, L WHERE X is TMP, X login L, X in_group G, |
193 2. return the result of Any X, L WHERE X is TMP, X login L, X in_group G, |
212 def test_complex_invariant(self): |
212 def test_complex_invariant(self): |
213 """ |
213 """ |
214 1. retrieve Any X,L,AA WHERE X login L, X modification_date AA from system and ldap sources, store |
214 1. retrieve Any X,L,AA WHERE X login L, X modification_date AA from system and ldap sources, store |
215 concatenation of results into a temporary table |
215 concatenation of results into a temporary table |
216 2. return the result of Any X,L,AA WHERE %s owned_by X, X login L, X modification_date AA |
216 2. return the result of Any X,L,AA WHERE %s owned_by X, X login L, X modification_date AA |
217 on the system source |
217 on the system source |
218 """ |
218 """ |
219 ueid = self.session.user.eid |
219 ueid = self.session.user.eid |
220 self._test('Any X,L,AA WHERE E eid %(x)s, E owned_by X, X login L, X modification_date AA', {'x': ueid}, |
220 self._test('Any X,L,AA WHERE E eid %(x)s, E owned_by X, X login L, X modification_date AA', {'x': ueid}, |
221 {self.system: {'x': s[0], 'X': s[0], 'owned_by': s[0]}, |
221 {self.system: {'x': s[0], 'X': s[0], 'owned_by': s[0]}, |
222 self.ldap : {'X': s[0]}}, True) |
222 self.ldap : {'X': s[0]}}, True) |
231 def test_complex_multiple(self): |
231 def test_complex_multiple(self): |
232 """ |
232 """ |
233 1. retrieve Any X,A,Y,B WHERE X login A, Y login B from system and ldap sources, store |
233 1. retrieve Any X,A,Y,B WHERE X login A, Y login B from system and ldap sources, store |
234 cartesian product of results into a temporary table |
234 cartesian product of results into a temporary table |
235 2. return the result of Any X,Y WHERE X login 'syt', Y login 'adim' |
235 2. return the result of Any X,Y WHERE X login 'syt', Y login 'adim' |
236 on the system source |
236 on the system source |
237 """ |
237 """ |
238 ueid = self.session.user.eid |
238 ueid = self.session.user.eid |
239 self._test('Any X,Y WHERE X login "syt", Y login "adim"', {'x': ueid}, |
239 self._test('Any X,Y WHERE X login "syt", Y login "adim"', {'x': ueid}, |
240 {self.system: {'Y': s[0], 'X': s[0]}, |
240 {self.system: {'Y': s[0], 'X': s[0]}, |
241 self.ldap: {'Y': s[0], 'X': s[0]}}, True) |
241 self.ldap: {'Y': s[0], 'X': s[0]}}, True) |
242 |
242 |
243 def test_complex_aggregat(self): |
243 def test_complex_aggregat(self): |
244 solindexes = set(range(len([e for e in self.schema.entities() if not e.is_final()]))) |
244 solindexes = set(range(len([e for e in self.schema.entities() if not e.is_final()]))) |
245 self._test('Any MAX(X)', |
245 self._test('Any MAX(X)', |
246 {self.system: {'X': solindexes}}, False) |
246 {self.system: {'X': solindexes}}, False) |
247 |
247 |
248 def test_complex_optional(self): |
248 def test_complex_optional(self): |
249 ueid = self.session.user.eid |
249 ueid = self.session.user.eid |
250 self._test('Any U WHERE WF wf_info_for X, X eid %(x)s, WF owned_by U?, WF from_state FS', {'x': ueid}, |
250 self._test('Any U WHERE WF wf_info_for X, X eid %(x)s, WF owned_by U?, WF from_state FS', {'x': ueid}, |
251 {self.system: {'WF': s[0], 'FS': s[0], 'U': s[0], |
251 {self.system: {'WF': s[0], 'FS': s[0], 'U': s[0], |
252 'from_state': s[0], 'owned_by': s[0], 'wf_info_for': s[0], |
252 'from_state': s[0], 'owned_by': s[0], 'wf_info_for': s[0], |
253 'x': s[0]}}, |
253 'x': s[0]}}, |
254 False) |
254 False) |
255 |
255 |
256 def test_exists4(self): |
256 def test_exists4(self): |
257 """ |
257 """ |
258 State S could come from both rql source and system source, |
258 State S could come from both rql source and system source, |
259 but since X cannot come from the rql source, the solution |
259 but since X cannot come from the rql source, the solution |
260 {self.rql : 'S'} must be removed |
260 {self.rql : 'S'} must be removed |
261 """ |
261 """ |
262 self._test('Any G,L WHERE X in_group G, X login L, G name "managers", ' |
262 self._test('Any G,L WHERE X in_group G, X login L, G name "managers", ' |
263 'EXISTS(X copain T, T login L, T login in ("comme", "cochon")) OR ' |
263 'EXISTS(X copain T, T login L, T login in ("comme", "cochon")) OR ' |
264 'EXISTS(X in_state S, S name "pascontent", NOT X copain T2, T2 login "billy")', |
264 'EXISTS(X in_state S, S name "pascontent", NOT X copain T2, T2 login "billy")', |
265 {self.system: {'X': s[0], 'S': s[0], 'T2': s[0], 'T': s[0], 'G': s[0], 'copain': s[0], 'in_group': s[0]}, |
265 {self.system: {'X': s[0], 'S': s[0], 'T2': s[0], 'T': s[0], 'G': s[0], 'copain': s[0], 'in_group': s[0]}, |
266 self.ldap: {'X': s[0], 'T2': s[0], 'T': s[0]}}, |
266 self.ldap: {'X': s[0], 'T2': s[0], 'T': s[0]}}, |
267 True) |
267 True) |
268 |
268 |
269 def test_relation_need_split(self): |
269 def test_relation_need_split(self): |
270 self._test('Any X, S WHERE X in_state S', |
270 self._test('Any X, S WHERE X in_state S', |
271 {self.system: {'X': s[0, 1, 2], 'S': s[0, 1, 2]}, |
271 {self.system: {'X': s[0, 1, 2], 'S': s[0, 1, 2]}, |
272 self.rql: {'X': s[2], 'S': s[2]}}, |
272 self.rql: {'X': s[2], 'S': s[2]}}, |
273 True) |
273 True) |
274 |
274 |
275 def test_not_relation_need_split(self): |
275 def test_not_relation_need_split(self): |
276 self._test('Any SN WHERE NOT X in_state S, S name SN', |
276 self._test('Any SN WHERE NOT X in_state S, S name SN', |
277 {self.rql: {'X': s[2], 'S': s[0, 1, 2]}, |
277 {self.rql: {'X': s[2], 'S': s[0, 1, 2]}, |
278 self.system: {'X': s[0, 1, 2], 'S': s[0, 1, 2]}}, |
278 self.system: {'X': s[0, 1, 2], 'S': s[0, 1, 2]}}, |
279 True) |
279 True) |
280 |
280 |
281 def test_not_relation_no_split_external(self): |
281 def test_not_relation_no_split_external(self): |
282 repo._type_source_cache[999999] = ('Note', 'cards', 999999) |
282 repo._type_source_cache[999999] = ('Note', 'cards', 999999) |
283 # similar to the above test but with an eid coming from the external source. |
283 # similar to the above test but with an eid coming from the external source. |
284 # the same plan may be used, since we won't find any record in the system source |
284 # the same plan may be used, since we won't find any record in the system source |
285 # linking 9999999 to a state |
285 # linking 9999999 to a state |
286 self._test('Any SN WHERE NOT X in_state S, X eid %(x)s, S name SN', |
286 self._test('Any SN WHERE NOT X in_state S, X eid %(x)s, S name SN', |
287 {'x': 999999}, |
287 {'x': 999999}, |
288 {self.rql: {'x': s[0], 'S': s[0]}, |
288 {self.rql: {'x': s[0], 'S': s[0]}, |
289 self.system: {'x': s[0], 'S': s[0]}}, |
289 self.system: {'x': s[0], 'S': s[0]}}, |
290 False) |
290 False) |
339 self._test('Any X,AD,AE WHERE E eid %(x)s, E multisource_crossed_rel X, X in_state AD, AD name AE', |
339 self._test('Any X,AD,AE WHERE E eid %(x)s, E multisource_crossed_rel X, X in_state AD, AD name AE', |
340 {'x': 999999}, |
340 {'x': 999999}, |
341 {self.rql: {'X': s[0], 'AD': s[0], 'multisource_crossed_rel': s[0], 'x': s[0]}, |
341 {self.rql: {'X': s[0], 'AD': s[0], 'multisource_crossed_rel': s[0], 'x': s[0]}, |
342 self.system: {'X': s[0], 'AD': s[0], 'multisource_crossed_rel': s[0], 'x': s[0]}}, |
342 self.system: {'X': s[0], 'AD': s[0], 'multisource_crossed_rel': s[0], 'x': s[0]}}, |
343 True) |
343 True) |
344 |
344 |
345 def test_version_crossed_depends_on_2(self): |
345 def test_version_crossed_depends_on_2(self): |
346 repo._type_source_cache[999999] = ('Note', 'system', 999999) |
346 repo._type_source_cache[999999] = ('Note', 'system', 999999) |
347 self._test('Any X,AD,AE WHERE E eid %(x)s, E multisource_crossed_rel X, X in_state AD, AD name AE', |
347 self._test('Any X,AD,AE WHERE E eid %(x)s, E multisource_crossed_rel X, X in_state AD, AD name AE', |
348 {'x': 999999}, |
348 {'x': 999999}, |
349 {self.rql: {'X': s[0], 'AD': s[0]}, |
349 {self.rql: {'X': s[0], 'AD': s[0]}, |
385 """retrieve entities only supported by the system source |
385 """retrieve entities only supported by the system source |
386 """ |
386 """ |
387 self._test('CWGroup X LIMIT 10 OFFSET 10', |
387 self._test('CWGroup X LIMIT 10 OFFSET 10', |
388 [('OneFetchStep', [('Any X LIMIT 10 OFFSET 10 WHERE X is CWGroup', [{'X': 'CWGroup'}])], |
388 [('OneFetchStep', [('Any X LIMIT 10 OFFSET 10 WHERE X is CWGroup', [{'X': 'CWGroup'}])], |
389 10, 10, [self.system], {}, [])]) |
389 10, 10, [self.system], {}, [])]) |
390 |
390 |
391 def test_simple_system_ldap(self): |
391 def test_simple_system_ldap(self): |
392 """retrieve CWUser X from both sources and return concatenation of results |
392 """retrieve CWUser X from both sources and return concatenation of results |
393 """ |
393 """ |
394 self._test('CWUser X', |
394 self._test('CWUser X', |
395 [('OneFetchStep', [('Any X WHERE X is CWUser', [{'X': 'CWUser'}])], |
395 [('OneFetchStep', [('Any X WHERE X is CWUser', [{'X': 'CWUser'}])], |
396 None, None, [self.ldap, self.system], {}, [])]) |
396 None, None, [self.ldap, self.system], {}, [])]) |
397 |
397 |
398 def test_simple_system_ldap_limit(self): |
398 def test_simple_system_ldap_limit(self): |
399 """retrieve CWUser X from both sources and return concatenation of results |
399 """retrieve CWUser X from both sources and return concatenation of results |
400 """ |
400 """ |
401 self._test('CWUser X LIMIT 10', |
401 self._test('CWUser X LIMIT 10', |
402 [('OneFetchStep', [('Any X LIMIT 10 WHERE X is CWUser', [{'X': 'CWUser'}])], |
402 [('OneFetchStep', [('Any X LIMIT 10 WHERE X is CWUser', [{'X': 'CWUser'}])], |
426 [('AggrStep', 'Any COUNT(X)', None, None, 'table0', None, [ |
426 [('AggrStep', 'Any COUNT(X)', None, None, 'table0', None, [ |
427 ('FetchStep', [('Any COUNT(X) WHERE X is CWUser', [{'X': 'CWUser'}])], |
427 ('FetchStep', [('Any COUNT(X) WHERE X is CWUser', [{'X': 'CWUser'}])], |
428 [self.ldap, self.system], {}, {'COUNT(X)': 'table0.C0'}, []), |
428 [self.ldap, self.system], {}, {'COUNT(X)': 'table0.C0'}, []), |
429 ]), |
429 ]), |
430 ]) |
430 ]) |
431 |
431 |
432 def test_simple_system_rql(self): |
432 def test_simple_system_rql(self): |
433 """retrieve Card X from both sources and return concatenation of results |
433 """retrieve Card X from both sources and return concatenation of results |
434 """ |
434 """ |
435 self._test('Any X, XT WHERE X is Card, X title XT', |
435 self._test('Any X, XT WHERE X is Card, X title XT', |
436 [('OneFetchStep', [('Any X,XT WHERE X is Card, X title XT', [{'X': 'Card', 'XT': 'String'}])], |
436 [('OneFetchStep', [('Any X,XT WHERE X is Card, X title XT', [{'X': 'Card', 'XT': 'String'}])], |
437 None, None, [self.rql, self.system], {}, [])]) |
437 None, None, [self.rql, self.system], {}, [])]) |
438 |
438 |
439 def test_simple_eid_specified(self): |
439 def test_simple_eid_specified(self): |
440 """retrieve CWUser X from system source (eid is specified, can locate the entity) |
440 """retrieve CWUser X from system source (eid is specified, can locate the entity) |
441 """ |
441 """ |
442 ueid = self.session.user.eid |
442 ueid = self.session.user.eid |
443 self._test('Any X,L WHERE X eid %(x)s, X login L', |
443 self._test('Any X,L WHERE X eid %(x)s, X login L', |
444 [('OneFetchStep', [('Any X,L WHERE X eid %s, X login L'%ueid, [{'X': 'CWUser', 'L': 'String'}])], |
444 [('OneFetchStep', [('Any X,L WHERE X eid %s, X login L'%ueid, [{'X': 'CWUser', 'L': 'String'}])], |
445 None, None, [self.system], {}, [])], |
445 None, None, [self.system], {}, [])], |
446 {'x': ueid}) |
446 {'x': ueid}) |
447 |
447 |
448 def test_simple_eid_invariant(self): |
448 def test_simple_eid_invariant(self): |
449 """retrieve CWUser X from system source (eid is specified, can locate the entity) |
449 """retrieve CWUser X from system source (eid is specified, can locate the entity) |
450 """ |
450 """ |
451 ueid = self.session.user.eid |
451 ueid = self.session.user.eid |
452 self._test('Any X WHERE X eid %(x)s', |
452 self._test('Any X WHERE X eid %(x)s', |
453 [('OneFetchStep', [('Any %s'%ueid, [{}])], |
453 [('OneFetchStep', [('Any %s'%ueid, [{}])], |
454 None, None, [self.system], {}, [])], |
454 None, None, [self.system], {}, [])], |
455 {'x': ueid}) |
455 {'x': ueid}) |
456 |
456 |
457 def test_simple_invariant(self): |
457 def test_simple_invariant(self): |
458 """retrieve CWUser X from system source only (X is invariant and in_group not supported by ldap source) |
458 """retrieve CWUser X from system source only (X is invariant and in_group not supported by ldap source) |
459 """ |
459 """ |
460 self._test('Any X WHERE X is CWUser, X in_group G, G name "users"', |
460 self._test('Any X WHERE X is CWUser, X in_group G, G name "users"', |
461 [('OneFetchStep', [('Any X WHERE X is CWUser, X in_group G, G name "users"', |
461 [('OneFetchStep', [('Any X WHERE X is CWUser, X in_group G, G name "users"', |
462 [{'X': 'CWUser', 'G': 'CWGroup'}])], |
462 [{'X': 'CWUser', 'G': 'CWGroup'}])], |
463 None, None, [self.system], {}, [])]) |
463 None, None, [self.system], {}, [])]) |
464 |
464 |
465 def test_complex_base(self): |
465 def test_complex_base(self): |
466 """ |
466 """ |
467 1. retrieve Any X, L WHERE X is CWUser, X login L from system and ldap sources, store |
467 1. retrieve Any X, L WHERE X is CWUser, X login L from system and ldap sources, store |
468 concatenation of results into a temporary table |
468 concatenation of results into a temporary table |
469 2. return the result of Any X, L WHERE X is TMP, X login LX in_group G, |
469 2. return the result of Any X, L WHERE X is TMP, X login LX in_group G, |
496 [self.system], {'X': 'table0.C0', 'X.login': 'table0.C1', 'L': 'table0.C1'}, []) |
496 [self.system], {'X': 'table0.C0', 'X.login': 'table0.C1', 'L': 'table0.C1'}, []) |
497 ]) |
497 ]) |
498 |
498 |
499 def test_complex_ordered(self): |
499 def test_complex_ordered(self): |
500 self._test('Any L ORDERBY L WHERE X login L', |
500 self._test('Any L ORDERBY L WHERE X login L', |
501 [('AggrStep', 'Any L ORDERBY L', None, None, 'table0', None, |
501 [('AggrStep', 'Any L ORDERBY L', None, None, 'table0', None, |
502 [('FetchStep', [('Any L WHERE X login L, X is CWUser', |
502 [('FetchStep', [('Any L WHERE X login L, X is CWUser', |
503 [{'X': 'CWUser', 'L': 'String'}])], |
503 [{'X': 'CWUser', 'L': 'String'}])], |
504 [self.ldap, self.system], {}, {'X.login': 'table0.C0', 'L': 'table0.C0'}, []), |
504 [self.ldap, self.system], {}, {'X.login': 'table0.C0', 'L': 'table0.C0'}, []), |
505 ]) |
505 ]) |
506 ]) |
506 ]) |
507 |
507 |
508 def test_complex_ordered_limit_offset(self): |
508 def test_complex_ordered_limit_offset(self): |
509 self._test('Any L ORDERBY L LIMIT 10 OFFSET 10 WHERE X login L', |
509 self._test('Any L ORDERBY L LIMIT 10 OFFSET 10 WHERE X login L', |
510 [('AggrStep', 'Any L ORDERBY L', 10, 10, 'table0', None, |
510 [('AggrStep', 'Any L ORDERBY L', 10, 10, 'table0', None, |
511 [('FetchStep', [('Any L WHERE X login L, X is CWUser', |
511 [('FetchStep', [('Any L WHERE X login L, X is CWUser', |
512 [{'X': 'CWUser', 'L': 'String'}])], |
512 [{'X': 'CWUser', 'L': 'String'}])], |
513 [self.ldap, self.system], {}, {'X.login': 'table0.C0', 'L': 'table0.C0'}, []), |
513 [self.ldap, self.system], {}, {'X.login': 'table0.C0', 'L': 'table0.C0'}, []), |
514 ]) |
514 ]) |
515 ]) |
515 ]) |
516 |
516 |
517 def test_complex_invariant_ordered(self): |
517 def test_complex_invariant_ordered(self): |
518 """ |
518 """ |
519 1. retrieve Any X,AA WHERE X modification_date AA from system and ldap sources, store |
519 1. retrieve Any X,AA WHERE X modification_date AA from system and ldap sources, store |
520 concatenation of results into a temporary table |
520 concatenation of results into a temporary table |
521 2. return the result of Any X,AA ORDERBY AA WHERE %s owned_by X, X modification_date AA |
521 2. return the result of Any X,AA ORDERBY AA WHERE %s owned_by X, X modification_date AA |
541 def test_complex_invariant(self): |
541 def test_complex_invariant(self): |
542 """ |
542 """ |
543 1. retrieve Any X,L,AA WHERE X login L, X modification_date AA from system and ldap sources, store |
543 1. retrieve Any X,L,AA WHERE X login L, X modification_date AA from system and ldap sources, store |
544 concatenation of results into a temporary table |
544 concatenation of results into a temporary table |
545 2. return the result of Any X,L,AA WHERE %s owned_by X, X login L, X modification_date AA |
545 2. return the result of Any X,L,AA WHERE %s owned_by X, X login L, X modification_date AA |
546 on the system source |
546 on the system source |
547 """ |
547 """ |
548 ueid = self.session.user.eid |
548 ueid = self.session.user.eid |
549 self._test('Any X,L,AA WHERE E eid %(x)s, E owned_by X, X login L, X modification_date AA', |
549 self._test('Any X,L,AA WHERE E eid %(x)s, E owned_by X, X login L, X modification_date AA', |
550 [('FetchStep', [('Any X,L,AA WHERE X login L, X modification_date AA, X is CWUser', |
550 [('FetchStep', [('Any X,L,AA WHERE X login L, X modification_date AA, X is CWUser', |
551 [{'AA': 'Datetime', 'X': 'CWUser', 'L': 'String'}])], |
551 [{'AA': 'Datetime', 'X': 'CWUser', 'L': 'String'}])], |
591 1. retrieve CWUser X from system and ldap sources, Person X from system source only, store |
591 1. retrieve CWUser X from system and ldap sources, Person X from system source only, store |
592 each result in the same temp table |
592 each result in the same temp table |
593 2. return content of the table sorted |
593 2. return content of the table sorted |
594 """ |
594 """ |
595 self._test('Any X,F ORDERBY F WHERE X firstname F', |
595 self._test('Any X,F ORDERBY F WHERE X firstname F', |
596 [('AggrStep', 'Any X,F ORDERBY F', None, None, 'table0', None, |
596 [('AggrStep', 'Any X,F ORDERBY F', None, None, 'table0', None, |
597 [('FetchStep', [('Any X,F WHERE X firstname F, X is CWUser', |
597 [('FetchStep', [('Any X,F WHERE X firstname F, X is CWUser', |
598 [{'X': 'CWUser', 'F': 'String'}])], |
598 [{'X': 'CWUser', 'F': 'String'}])], |
599 [self.ldap, self.system], {}, |
599 [self.ldap, self.system], {}, |
600 {'X': 'table0.C0', 'X.firstname': 'table0.C1', 'F': 'table0.C1'}, []), |
600 {'X': 'table0.C0', 'X.firstname': 'table0.C1', 'F': 'table0.C1'}, []), |
601 ('FetchStep', [('Any X,F WHERE X firstname F, X is Personne', |
601 ('FetchStep', [('Any X,F WHERE X firstname F, X is Personne', |
602 [{'X': 'Personne', 'F': 'String'}])], |
602 [{'X': 'Personne', 'F': 'String'}])], |
603 [self.system], {}, |
603 [self.system], {}, |
604 {'X': 'table0.C0', 'X.firstname': 'table0.C1', 'F': 'table0.C1'}, []), |
604 {'X': 'table0.C0', 'X.firstname': 'table0.C1', 'F': 'table0.C1'}, []), |
605 ]), |
605 ]), |
606 ]) |
606 ]) |
607 |
607 |
608 def test_complex_multiple(self): |
608 def test_complex_multiple(self): |
609 """ |
609 """ |
610 1. retrieve Any X,A,Y,B WHERE X login A, Y login B from system and ldap sources, store |
610 1. retrieve Any X,A,Y,B WHERE X login A, Y login B from system and ldap sources, store |
611 cartesian product of results into a temporary table |
611 cartesian product of results into a temporary table |
612 2. return the result of Any X,Y WHERE X login 'syt', Y login 'adim' |
612 2. return the result of Any X,Y WHERE X login 'syt', Y login 'adim' |
613 on the system source |
613 on the system source |
614 """ |
614 """ |
615 ueid = self.session.user.eid |
615 ueid = self.session.user.eid |
616 self._test('Any X,Y WHERE X login "syt", Y login "adim"', |
616 self._test('Any X,Y WHERE X login "syt", Y login "adim"', |
617 [('FetchStep', |
617 [('FetchStep', |
618 [('Any X WHERE X login "syt", X is CWUser', [{'X': 'CWUser'}])], |
618 [('Any X WHERE X login "syt", X is CWUser', [{'X': 'CWUser'}])], |
625 ('OneFetchStep', |
625 ('OneFetchStep', |
626 [('Any X,Y WHERE X is CWUser, Y is CWUser', [{'X': 'CWUser', 'Y': 'CWUser'}])], |
626 [('Any X,Y WHERE X is CWUser, Y is CWUser', [{'X': 'CWUser', 'Y': 'CWUser'}])], |
627 None, None, [self.system], |
627 None, None, [self.system], |
628 {'X': 'table0.C0', 'Y': 'table1.C0'}, []) |
628 {'X': 'table0.C0', 'Y': 'table1.C0'}, []) |
629 ], {'x': ueid}) |
629 ], {'x': ueid}) |
630 |
630 |
631 def test_complex_multiple_limit_offset(self): |
631 def test_complex_multiple_limit_offset(self): |
632 """ |
632 """ |
633 1. retrieve Any X,A,Y,B WHERE X login A, Y login B from system and ldap sources, store |
633 1. retrieve Any X,A,Y,B WHERE X login A, Y login B from system and ldap sources, store |
634 cartesian product of results into a temporary table |
634 cartesian product of results into a temporary table |
635 2. return the result of Any X,Y WHERE X login 'syt', Y login 'adim' |
635 2. return the result of Any X,Y WHERE X login 'syt', Y login 'adim' |
636 on the system source |
636 on the system source |
637 """ |
637 """ |
638 ueid = self.session.user.eid |
638 ueid = self.session.user.eid |
639 self._test('Any X,Y LIMIT 10 OFFSET 10 WHERE X login "syt", Y login "adim"', |
639 self._test('Any X,Y LIMIT 10 OFFSET 10 WHERE X login "syt", Y login "adim"', |
640 [('FetchStep', |
640 [('FetchStep', |
641 [('Any X WHERE X login "syt", X is CWUser', [{'X': 'CWUser'}])], |
641 [('Any X WHERE X login "syt", X is CWUser', [{'X': 'CWUser'}])], |
646 ('OneFetchStep', |
646 ('OneFetchStep', |
647 [('Any X,Y LIMIT 10 OFFSET 10 WHERE X is CWUser, Y is CWUser', [{'X': 'CWUser', 'Y': 'CWUser'}])], |
647 [('Any X,Y LIMIT 10 OFFSET 10 WHERE X is CWUser, Y is CWUser', [{'X': 'CWUser', 'Y': 'CWUser'}])], |
648 10, 10, [self.system], |
648 10, 10, [self.system], |
649 {'X': 'table0.C0', 'Y': 'table1.C0'}, []) |
649 {'X': 'table0.C0', 'Y': 'table1.C0'}, []) |
650 ], {'x': ueid}) |
650 ], {'x': ueid}) |
651 |
651 |
652 def test_complex_aggregat(self): |
652 def test_complex_aggregat(self): |
653 self._test('Any MAX(X)', |
653 self._test('Any MAX(X)', |
654 [('OneFetchStep', |
654 [('OneFetchStep', |
655 [('Any MAX(X)', X_ALL_SOLS)], |
655 [('Any MAX(X)', X_ALL_SOLS)], |
656 None, None, [self.system], {}, []) |
656 None, None, [self.system], {}, []) |
657 ]) |
657 ]) |
658 |
658 |
659 def test_complex_typed_aggregat(self): |
659 def test_complex_typed_aggregat(self): |
660 self._test('Any MAX(X) WHERE X is Card', |
660 self._test('Any MAX(X) WHERE X is Card', |
661 [('AggrStep', 'Any MAX(X)', None, None, 'table0', None, |
661 [('AggrStep', 'Any MAX(X)', None, None, 'table0', None, |
662 [('FetchStep', |
662 [('FetchStep', |
663 [('Any MAX(X) WHERE X is Card', [{'X': 'Card'}])], |
663 [('Any MAX(X) WHERE X is Card', [{'X': 'Card'}])], |
664 [self.rql, self.system], {}, {'MAX(X)': 'table0.C0'}, []) |
664 [self.rql, self.system], {}, {'MAX(X)': 'table0.C0'}, []) |
665 ]) |
665 ]) |
666 ]) |
666 ]) |
667 |
667 |
668 def test_complex_greater_eid(self): |
668 def test_complex_greater_eid(self): |
669 self._test('Any X WHERE X eid > 12', |
669 self._test('Any X WHERE X eid > 12', |
670 [('OneFetchStep', |
670 [('OneFetchStep', |
671 [('Any X WHERE X eid > 12', X_ALL_SOLS)], |
671 [('Any X WHERE X eid > 12', X_ALL_SOLS)], |
672 None, None, [self.system], {}, []) |
672 None, None, [self.system], {}, []) |
673 ]) |
673 ]) |
674 |
674 |
675 def test_complex_greater_typed_eid(self): |
675 def test_complex_greater_typed_eid(self): |
676 self._test('Any X WHERE X eid > 12, X is Card', |
676 self._test('Any X WHERE X eid > 12, X is Card', |
677 [('OneFetchStep', |
677 [('OneFetchStep', |
678 [('Any X WHERE X eid > 12, X is Card', [{'X': 'Card'}])], |
678 [('Any X WHERE X eid > 12, X is Card', [{'X': 'Card'}])], |
679 None, None, [self.system], {}, []) |
679 None, None, [self.system], {}, []) |
680 ]) |
680 ]) |
681 |
681 |
682 def test_complex_optional(self): |
682 def test_complex_optional(self): |
683 ueid = self.session.user.eid |
683 ueid = self.session.user.eid |
684 self._test('Any U WHERE WF wf_info_for X, X eid %(x)s, WF owned_by U?, WF from_state FS', |
684 self._test('Any U WHERE WF wf_info_for X, X eid %(x)s, WF owned_by U?, WF from_state FS', |
685 [('OneFetchStep', [('Any U WHERE WF wf_info_for 5, WF owned_by U?, WF from_state FS', |
685 [('OneFetchStep', [('Any U WHERE WF wf_info_for 5, WF owned_by U?, WF from_state FS', |
686 [{'WF': 'TrInfo', 'FS': 'State', 'U': 'CWUser'}])], |
686 [{'WF': 'TrInfo', 'FS': 'State', 'U': 'CWUser'}])], |
693 [('OneFetchStep', [('Any U WHERE WF wf_info_for 5, WF owned_by U?, WF from_state FS', |
693 [('OneFetchStep', [('Any U WHERE WF wf_info_for 5, WF owned_by U?, WF from_state FS', |
694 [{'WF': 'TrInfo', 'FS': 'State', 'U': 'CWUser'}])], |
694 [{'WF': 'TrInfo', 'FS': 'State', 'U': 'CWUser'}])], |
695 None, None, [self.system], {}, [])], |
695 None, None, [self.system], {}, [])], |
696 {'x': ueid}) |
696 {'x': ueid}) |
697 |
697 |
698 |
698 |
699 def test_3sources_ambigous(self): |
699 def test_3sources_ambigous(self): |
700 self._test('Any X,T WHERE X owned_by U, U login "syt", X title T', |
700 self._test('Any X,T WHERE X owned_by U, U login "syt", X title T', |
701 [('FetchStep', [('Any X,T WHERE X title T, X is Card', [{'X': 'Card', 'T': 'String'}])], |
701 [('FetchStep', [('Any X,T WHERE X title T, X is Card', [{'X': 'Card', 'T': 'String'}])], |
702 [self.rql, self.system], None, |
702 [self.rql, self.system], None, |
703 {'T': 'table0.C1', 'X': 'table0.C0', 'X.title': 'table0.C1'}, []), |
703 {'T': 'table0.C1', 'X': 'table0.C0', 'X.title': 'table0.C1'}, []), |
734 None, None, [self.system], |
734 None, None, [self.system], |
735 {'VR': 'table1.C1', 'V': 'table1.C0', 'V.creation_date': 'table1.C1', 'X.creation_date': 'table0.C0'}, []) |
735 {'VR': 'table1.C1', 'V': 'table1.C0', 'V.creation_date': 'table1.C1', 'X.creation_date': 'table0.C0'}, []) |
736 ]) |
736 ]) |
737 |
737 |
738 def test_outer_supported_rel1(self): |
738 def test_outer_supported_rel1(self): |
739 # both system and rql support all variables, can be |
739 # both system and rql support all variables, can be |
740 self._test('Any X, R WHERE X is Note, X in_state S, X type R, ' |
740 self._test('Any X, R WHERE X is Note, X in_state S, X type R, ' |
741 'NOT EXISTS(Y is Note, Y in_state S, Y type R, X identity Y)', |
741 'NOT EXISTS(Y is Note, Y in_state S, Y type R, X identity Y)', |
742 [('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', |
742 [('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', |
743 [{'Y': 'Note', 'X': 'Note', 'S': 'State', 'R': 'String'}])], |
743 [{'Y': 'Note', 'X': 'Note', 'S': 'State', 'R': 'String'}])], |
744 None, None, |
744 None, None, |
745 [self.rql, self.system], {}, []) |
745 [self.rql, self.system], {}, []) |
746 ]) |
746 ]) |
747 |
747 |
748 def test_not_identity(self): |
748 def test_not_identity(self): |
749 # both system and rql support all variables, can be |
749 # both system and rql support all variables, can be |
750 self._test('Any X WHERE NOT X identity U, U eid %s' % self.session.user.eid, |
750 self._test('Any X WHERE NOT X identity U, U eid %s' % self.session.user.eid, |
751 [('OneFetchStep', |
751 [('OneFetchStep', |
752 [('Any X WHERE NOT X identity 5, X is CWUser', [{'X': 'CWUser'}])], |
752 [('Any X WHERE NOT X identity 5, X is CWUser', [{'X': 'CWUser'}])], |
753 None, None, |
753 None, None, |
754 [self.ldap, self.system], {}, []) |
754 [self.ldap, self.system], {}, []) |
767 ('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', |
767 ('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', |
768 [{'Y': 'Note', 'X': 'CWUser', 'S': 'State', 'R': 'String', 'A': 'State'}])], |
768 [{'Y': 'Note', 'X': 'CWUser', 'S': 'State', 'R': 'String', 'A': 'State'}])], |
769 None, None, [self.system], |
769 None, None, [self.system], |
770 {'A': 'table0.C0', 'X': 'table1.C0', 'X.login': 'table1.C1', 'R': 'table1.C1', 'Y.type': 'table0.C1'}, []) |
770 {'A': 'table0.C0', 'X': 'table1.C0', 'X.login': 'table1.C1', 'R': 'table1.C1', 'Y.type': 'table0.C1'}, []) |
771 ]) |
771 ]) |
772 |
772 |
773 def test_security_has_text(self): |
773 def test_security_has_text(self): |
774 # use a guest user |
774 # use a guest user |
775 self.session = self._user_session()[1] |
775 self.session = self._user_session()[1] |
776 self._test('Any X WHERE X has_text "bla"', |
776 self._test('Any X WHERE X has_text "bla"', |
777 [('FetchStep', [('Any E WHERE E type "X", E is Note', [{'E': 'Note'}])], |
777 [('FetchStep', [('Any E WHERE E type "X", E is Note', [{'E': 'Note'}])], |
826 {'X': 'Comment'}, {'X': 'Division'}, {'X': 'CWUser'}, |
826 {'X': 'Comment'}, {'X': 'Division'}, {'X': 'CWUser'}, |
827 {'X': 'Email'}, {'X': 'EmailThread'}, {'X': 'File'}, |
827 {'X': 'Email'}, {'X': 'EmailThread'}, {'X': 'File'}, |
828 {'X': 'Folder'}, {'X': 'Image'}, {'X': 'Note'}, |
828 {'X': 'Folder'}, {'X': 'Image'}, {'X': 'Note'}, |
829 {'X': 'Personne'}, {'X': 'Societe'}, {'X': 'State'}, |
829 {'X': 'Personne'}, {'X': 'Societe'}, {'X': 'State'}, |
830 {'X': 'SubDivision'}, {'X': 'Tag'}, {'X': 'Transition'}])], |
830 {'X': 'SubDivision'}, {'X': 'Tag'}, {'X': 'Transition'}])], |
831 10, 10, [self.system], {'X': 'table0.C0'}, []) |
831 10, 10, [self.system], {'X': 'table0.C0'}, []) |
832 ]) |
832 ]) |
833 |
833 |
834 def test_security_user(self): |
834 def test_security_user(self): |
835 """a guest user trying to see another user: EXISTS(X owned_by U) is automatically inserted""" |
835 """a guest user trying to see another user: EXISTS(X owned_by U) is automatically inserted""" |
836 # use a guest user |
836 # use a guest user |
837 self.session = self._user_session()[1] |
837 self.session = self._user_session()[1] |
838 self._test('Any X WHERE X login "bla"', |
838 self._test('Any X WHERE X login "bla"', |
840 [('Any X WHERE X login "bla", X is CWUser', [{'X': 'CWUser'}])], |
840 [('Any X WHERE X login "bla", X is CWUser', [{'X': 'CWUser'}])], |
841 [self.ldap, self.system], None, {'X': 'table0.C0'}, []), |
841 [self.ldap, self.system], None, {'X': 'table0.C0'}, []), |
842 ('OneFetchStep', |
842 ('OneFetchStep', |
843 [('Any X WHERE EXISTS(X owned_by 5), X is CWUser', [{'X': 'CWUser'}])], |
843 [('Any X WHERE EXISTS(X owned_by 5), X is CWUser', [{'X': 'CWUser'}])], |
844 None, None, [self.system], {'X': 'table0.C0'}, [])]) |
844 None, None, [self.system], {'X': 'table0.C0'}, [])]) |
845 |
845 |
846 def test_security_complex_has_text(self): |
846 def test_security_complex_has_text(self): |
847 # use a guest user |
847 # use a guest user |
848 self.session = self._user_session()[1] |
848 self.session = self._user_session()[1] |
849 self._test('Any X WHERE X has_text "bla", X firstname "bla"', |
849 self._test('Any X WHERE X has_text "bla", X firstname "bla"', |
850 [('FetchStep', [('Any X WHERE X firstname "bla", X is CWUser', [{'X': 'CWUser'}])], |
850 [('FetchStep', [('Any X WHERE X firstname "bla", X is CWUser', [{'X': 'CWUser'}])], |
877 def test_security_complex_aggregat(self): |
877 def test_security_complex_aggregat(self): |
878 # use a guest user |
878 # use a guest user |
879 self.session = self._user_session()[1] |
879 self.session = self._user_session()[1] |
880 self._test('Any MAX(X)', |
880 self._test('Any MAX(X)', |
881 [('FetchStep', [('Any E WHERE E type "X", E is Note', [{'E': 'Note'}])], |
881 [('FetchStep', [('Any E WHERE E type "X", E is Note', [{'E': 'Note'}])], |
882 [self.rql, self.system], None, {'E': 'table1.C0'}, []), |
882 [self.rql, self.system], None, {'E': 'table1.C0'}, []), |
883 ('FetchStep', [('Any X WHERE X is CWUser', [{'X': 'CWUser'}])], |
883 ('FetchStep', [('Any X WHERE X is CWUser', [{'X': 'CWUser'}])], |
884 [self.ldap, self.system], None, {'X': 'table2.C0'}, []), |
884 [self.ldap, self.system], None, {'X': 'table2.C0'}, []), |
885 ('UnionFetchStep', [ |
885 ('UnionFetchStep', [ |
886 ('FetchStep', [('Any X WHERE EXISTS(X owned_by 5), X is Basket', [{'X': 'Basket'}])], |
886 ('FetchStep', [('Any X WHERE EXISTS(X owned_by 5), X is Basket', [{'X': 'Basket'}])], |
887 [self.system], {}, {'X': 'table0.C0'}, []), |
887 [self.system], {}, {'X': 'table0.C0'}, []), |
888 ('UnionFetchStep', |
888 ('UnionFetchStep', |
889 [('FetchStep', [('Any X WHERE X is IN(Card, Note, State)', |
889 [('FetchStep', [('Any X WHERE X is IN(Card, Note, State)', |
890 [{'X': 'Card'}, {'X': 'Note'}, {'X': 'State'}])], |
890 [{'X': 'Card'}, {'X': 'Note'}, {'X': 'State'}])], |
891 [self.rql, self.system], {}, {'X': 'table0.C0'}, []), |
891 [self.rql, self.system], {}, {'X': 'table0.C0'}, []), |
892 ('FetchStep', |
892 ('FetchStep', |
893 [('Any X WHERE X is IN(Bookmark, Comment, Division, CWCache, CWConstraint, CWConstraintType, CWEType, CWAttribute, CWGroup, CWRelation, CWPermission, CWProperty, CWRType, Email, EmailAddress, EmailPart, EmailThread, File, Folder, Image, Personne, RQLExpression, Societe, SubDivision, Tag, TrInfo, Transition)', |
893 [('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)', |
894 sorted([{'X': 'Bookmark'}, {'X': 'Comment'}, {'X': 'Division'}, |
894 sorted([{'X': 'Bookmark'}, {'X': 'Comment'}, {'X': 'Division'}, |
895 {'X': 'CWCache'}, {'X': 'CWConstraint'}, {'X': 'CWConstraintType'}, |
895 {'X': 'CWCache'}, {'X': 'CWConstraint'}, {'X': 'CWConstraintType'}, |
896 {'X': 'CWEType'}, {'X': 'CWAttribute'}, {'X': 'CWGroup'}, |
896 {'X': 'CWEType'}, {'X': 'CWAttribute'}, {'X': 'CWGroup'}, |
897 {'X': 'CWRelation'}, {'X': 'CWPermission'}, {'X': 'CWProperty'}, |
897 {'X': 'CWRelation'}, {'X': 'CWPermission'}, {'X': 'CWProperty'}, |
898 {'X': 'CWRType'}, {'X': 'Email'}, {'X': 'EmailAddress'}, |
898 {'X': 'CWRType'}, {'X': 'Email'}, {'X': 'EmailAddress'}, |
904 ]), |
904 ]), |
905 ('FetchStep', [('Any X WHERE EXISTS(X owned_by 5), X is CWUser', [{'X': 'CWUser'}])], |
905 ('FetchStep', [('Any X WHERE EXISTS(X owned_by 5), X is CWUser', [{'X': 'CWUser'}])], |
906 [self.system], {'X': 'table2.C0'}, {'X': 'table0.C0'}, []), |
906 [self.system], {'X': 'table2.C0'}, {'X': 'table0.C0'}, []), |
907 ('FetchStep', [('Any X WHERE (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', |
907 ('FetchStep', [('Any X WHERE (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', |
908 [{'C': 'Division', 'E': 'Note', 'D': 'Affaire', 'G': 'SubDivision', 'F': 'Societe', 'I': 'Affaire', 'H': 'Affaire', 'J': 'Affaire', 'X': 'Affaire'}])], |
908 [{'C': 'Division', 'E': 'Note', 'D': 'Affaire', 'G': 'SubDivision', 'F': 'Societe', 'I': 'Affaire', 'H': 'Affaire', 'J': 'Affaire', 'X': 'Affaire'}])], |
909 [self.system], {'E': 'table1.C0'}, {'X': 'table0.C0'}, []), |
909 [self.system], {'E': 'table1.C0'}, {'X': 'table0.C0'}, []), |
910 ]), |
910 ]), |
911 ('OneFetchStep', [('Any MAX(X)', X_ALL_SOLS)], |
911 ('OneFetchStep', [('Any MAX(X)', X_ALL_SOLS)], |
912 None, None, [self.system], {'X': 'table0.C0'}, []) |
912 None, None, [self.system], {'X': 'table0.C0'}, []) |
913 ]) |
913 ]) |
914 |
914 |
915 def test_security_complex_aggregat2(self): |
915 def test_security_complex_aggregat2(self): |
916 # use a guest user |
916 # use a guest user |
917 self.session = self._user_session()[1] |
917 self.session = self._user_session()[1] |
918 self._test('Any ET, COUNT(X) GROUPBY ET ORDERBY ET WHERE X is ET', |
918 self._test('Any ET, COUNT(X) GROUPBY ET ORDERBY ET WHERE X is ET', |
919 [('FetchStep', [('Any X WHERE X is IN(Card, Note, State)', |
919 [('FetchStep', [('Any X WHERE X is IN(Card, Note, State)', |
920 [{'X': 'Card'}, {'X': 'Note'}, {'X': 'State'}])], |
920 [{'X': 'Card'}, {'X': 'Note'}, {'X': 'State'}])], |
921 [self.rql, self.system], None, {'X': 'table1.C0'}, []), |
921 [self.rql, self.system], None, {'X': 'table1.C0'}, []), |
922 ('FetchStep', [('Any E WHERE E type "X", E is Note', [{'E': 'Note'}])], |
922 ('FetchStep', [('Any E WHERE E type "X", E is Note', [{'E': 'Note'}])], |
923 [self.rql, self.system], None, {'E': 'table2.C0'}, []), |
923 [self.rql, self.system], None, {'E': 'table2.C0'}, []), |
937 ('FetchStep', [('Any ET,X WHERE X is ET, EXISTS(X owned_by 5), ET is CWEType, X is CWUser', |
937 ('FetchStep', [('Any ET,X WHERE X is ET, EXISTS(X owned_by 5), ET is CWEType, X is CWUser', |
938 [{'ET': 'CWEType', 'X': 'CWUser'}])], |
938 [{'ET': 'CWEType', 'X': 'CWUser'}])], |
939 [self.system], {'X': 'table3.C0'}, {'ET': 'table0.C0', 'X': 'table0.C1'}, []), |
939 [self.system], {'X': 'table3.C0'}, {'ET': 'table0.C0', 'X': 'table0.C1'}, []), |
940 # extra UnionFetchStep could be avoided but has no cost, so don't care |
940 # extra UnionFetchStep could be avoided but has no cost, so don't care |
941 ('UnionFetchStep', |
941 ('UnionFetchStep', |
942 [('FetchStep', [('Any ET,X WHERE X is ET, ET is CWEType, X is IN(Bookmark, Comment, Division, CWCache, CWConstraint, CWConstraintType, CWEType, CWAttribute, CWGroup, CWRelation, CWPermission, CWProperty, CWRType, Email, EmailAddress, EmailPart, EmailThread, File, Folder, Image, Personne, RQLExpression, Societe, SubDivision, Tag, TrInfo, Transition)', |
942 [('FetchStep', [('Any ET,X WHERE X is ET, ET is CWEType, 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)', |
943 [{'X': 'Bookmark', 'ET': 'CWEType'}, {'X': 'Comment', 'ET': 'CWEType'}, |
943 [{'X': 'Bookmark', 'ET': 'CWEType'}, {'X': 'Comment', 'ET': 'CWEType'}, |
944 {'X': 'Division', 'ET': 'CWEType'}, {'X': 'CWCache', 'ET': 'CWEType'}, |
944 {'X': 'Division', 'ET': 'CWEType'}, {'X': 'CWCache', 'ET': 'CWEType'}, |
945 {'X': 'CWConstraint', 'ET': 'CWEType'}, {'X': 'CWConstraintType', 'ET': 'CWEType'}, |
945 {'X': 'CWConstraint', 'ET': 'CWEType'}, {'X': 'CWConstraintType', 'ET': 'CWEType'}, |
946 {'X': 'CWEType', 'ET': 'CWEType'}, {'X': 'CWAttribute', 'ET': 'CWEType'}, |
946 {'X': 'CWEType', 'ET': 'CWEType'}, {'X': 'CWAttribute', 'ET': 'CWEType'}, |
947 {'X': 'CWGroup', 'ET': 'CWEType'}, {'X': 'CWRelation', 'ET': 'CWEType'}, |
947 {'X': 'CWGroup', 'ET': 'CWEType'}, {'X': 'CWRelation', 'ET': 'CWEType'}, |
1052 [('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', |
1052 [('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', |
1053 [{'X': 'Card', 'U': 'CWUser', 'XT': 'String'}])], |
1053 [{'X': 'Card', 'U': 'CWUser', 'XT': 'String'}])], |
1054 10, 10, [self.system], |
1054 10, 10, [self.system], |
1055 {'X': 'table0.C0', 'X.title': 'table0.C1', 'XT': 'table0.C1', 'U': 'table1.C0'}, []) |
1055 {'X': 'table0.C0', 'X.title': 'table0.C1', 'XT': 'table0.C1', 'U': 'table1.C0'}, []) |
1056 ]) |
1056 ]) |
1057 |
1057 |
1058 def test_exists_base(self): |
1058 def test_exists_base(self): |
1059 self._test('Any X,L,S WHERE X in_state S, X login L, EXISTS(X in_group G, G name "bougloup")', |
1059 self._test('Any X,L,S WHERE X in_state S, X login L, EXISTS(X in_group G, G name "bougloup")', |
1060 [('FetchStep', [('Any X,L WHERE X login L, X is CWUser', [{'X': 'CWUser', 'L': 'String'}])], |
1060 [('FetchStep', [('Any X,L WHERE X login L, X is CWUser', [{'X': 'CWUser', 'L': 'String'}])], |
1061 [self.ldap, self.system], None, {'X': 'table0.C0', 'X.login': 'table0.C1', 'L': 'table0.C1'}, []), |
1061 [self.ldap, self.system], None, {'X': 'table0.C0', 'X.login': 'table0.C1', 'L': 'table0.C1'}, []), |
1062 ('OneFetchStep', [("Any X,L,S WHERE X in_state S, X login L, " |
1062 ('OneFetchStep', [("Any X,L,S WHERE X in_state S, X login L, " |
1126 ('OneFetchStep', [('Any GN,L WHERE X in_group G, X login L, G name GN, EXISTS(X copain T, T is CWUser), NOT EXISTS(X copain T2, T2 is CWUser), G is CWGroup, X is CWUser', |
1126 ('OneFetchStep', [('Any GN,L WHERE X in_group G, X login L, G name GN, EXISTS(X copain T, T is CWUser), NOT EXISTS(X copain T2, T2 is CWUser), G is CWGroup, X is CWUser', |
1127 [{'G': 'CWGroup', 'GN': 'String', 'L': 'String', 'T': 'CWUser', 'T2': 'CWUser', 'X': 'CWUser'}])], |
1127 [{'G': 'CWGroup', 'GN': 'String', 'L': 'String', 'T': 'CWUser', 'T2': 'CWUser', 'X': 'CWUser'}])], |
1128 None, None, [self.system], |
1128 None, None, [self.system], |
1129 {'T': 'table0.C0', 'T2': 'table1.C0', |
1129 {'T': 'table0.C0', 'T2': 'table1.C0', |
1130 'X': 'table2.C1', 'X.login': 'table2.C0', 'L': 'table2.C0'}, [])]) |
1130 'X': 'table2.C1', 'X.login': 'table2.C0', 'L': 'table2.C0'}, [])]) |
1131 |
1131 |
1132 def test_exists_security_no_invariant(self): |
1132 def test_exists_security_no_invariant(self): |
1133 ueid = self.session.user.eid |
1133 ueid = self.session.user.eid |
1134 self._test('Any X,AA,AB,AC,AD ORDERBY AA WHERE X is CWUser, X login AA, X firstname AB, X surname AC, X modification_date AD, A eid %(B)s, \ |
1134 self._test('Any X,AA,AB,AC,AD ORDERBY AA WHERE X is CWUser, X login AA, X firstname AB, X surname AC, X modification_date AD, A eid %(B)s, \ |
1135 EXISTS(((X identity A) OR \ |
1135 EXISTS(((X identity A) OR \ |
1136 (EXISTS(X in_group C, C name IN("managers", "staff"), C is CWGroup))) OR \ |
1136 (EXISTS(X in_group C, C name IN("managers", "staff"), C is CWGroup))) OR \ |
1157 |
1157 |
1158 def test_relation_need_split(self): |
1158 def test_relation_need_split(self): |
1159 self._test('Any X, S WHERE X in_state S', |
1159 self._test('Any X, S WHERE X in_state S', |
1160 [('UnionStep', None, None, [ |
1160 [('UnionStep', None, None, [ |
1161 ('OneFetchStep', [('Any X,S WHERE X in_state S, S is State, X is IN(Affaire, CWUser)', |
1161 ('OneFetchStep', [('Any X,S WHERE X in_state S, S is State, X is IN(Affaire, CWUser)', |
1162 [{'X': 'Affaire', 'S': 'State'}, {'X': 'CWUser', 'S': 'State'}])], |
1162 [{'X': 'Affaire', 'S': 'State'}, {'X': 'CWUser', 'S': 'State'}])], |
1163 None, None, [self.system], {}, []), |
1163 None, None, [self.system], {}, []), |
1164 ('OneFetchStep', [('Any X,S WHERE X in_state S, S is State, X is Note', |
1164 ('OneFetchStep', [('Any X,S WHERE X in_state S, S is State, X is Note', |
1165 [{'X': 'Note', 'S': 'State'}])], |
1165 [{'X': 'Note', 'S': 'State'}])], |
1166 None, None, [self.rql, self.system], {}, []), |
1166 None, None, [self.rql, self.system], {}, []), |
1167 ])]) |
1167 ])]) |
1168 |
1168 |
1169 def test_relation_selection_need_split(self): |
1169 def test_relation_selection_need_split(self): |
1170 self._test('Any X,S,U WHERE X in_state S, X todo_by U', |
1170 self._test('Any X,S,U WHERE X in_state S, X todo_by U', |
1221 # given eid. The "NOT X in_state S, X eid %(x)s" expression is necessarily true |
1221 # given eid. The "NOT X in_state S, X eid %(x)s" expression is necessarily true |
1222 # in the source where %(x)s is not coming from and will be removed during rql |
1222 # in the source where %(x)s is not coming from and will be removed during rql |
1223 # generation for the external source |
1223 # generation for the external source |
1224 self._test('Any SN WHERE NOT X in_state S, X eid %(x)s, S name SN', |
1224 self._test('Any SN WHERE NOT X in_state S, X eid %(x)s, S name SN', |
1225 [('OneFetchStep', [('Any SN WHERE NOT 5 in_state S, S name SN, S is State', |
1225 [('OneFetchStep', [('Any SN WHERE NOT 5 in_state S, S name SN, S is State', |
1226 [{'S': 'State', 'SN': 'String'}])], |
1226 [{'S': 'State', 'SN': 'String'}])], |
1227 None, None, [self.rql, self.system], {}, [])], |
1227 None, None, [self.rql, self.system], {}, [])], |
1228 {'x': ueid}) |
1228 {'x': ueid}) |
1229 |
1229 |
1230 def test_not_relation_no_split_external(self): |
1230 def test_not_relation_no_split_external(self): |
1231 repo._type_source_cache[999999] = ('Note', 'cards', 999999) |
1231 repo._type_source_cache[999999] = ('Note', 'cards', 999999) |
1232 # similar to the above test but with an eid coming from the external source. |
1232 # similar to the above test but with an eid coming from the external source. |
1233 # the same plan may be used, since we won't find any record in the system source |
1233 # the same plan may be used, since we won't find any record in the system source |
1234 # linking 9999999 to a state |
1234 # linking 9999999 to a state |
1235 self._test('Any SN WHERE NOT X in_state S, X eid %(x)s, S name SN', |
1235 self._test('Any SN WHERE NOT X in_state S, X eid %(x)s, S name SN', |
1236 [('OneFetchStep', [('Any SN WHERE NOT 999999 in_state S, S name SN, S is State', |
1236 [('OneFetchStep', [('Any SN WHERE NOT 999999 in_state S, S name SN, S is State', |
1237 [{'S': 'State', 'SN': 'String'}])], |
1237 [{'S': 'State', 'SN': 'String'}])], |
1238 None, None, [self.rql, self.system], {}, [])], |
1238 None, None, [self.rql, self.system], {}, [])], |
1239 {'x': 999999}) |
1239 {'x': 999999}) |
1240 |
1240 |
1241 def test_not_relation_need_split(self): |
1241 def test_not_relation_need_split(self): |
1242 self._test('Any SN WHERE NOT X in_state S, S name SN', |
1242 self._test('Any SN WHERE NOT X in_state S, S name SN', |
1255 [{'S': 'State', 'SN': 'String', 'X': 'Affaire'}, |
1255 [{'S': 'State', 'SN': 'String', 'X': 'Affaire'}, |
1256 {'S': 'State', 'SN': 'String', 'X': 'CWUser'}])], |
1256 {'S': 'State', 'SN': 'String', 'X': 'CWUser'}])], |
1257 None, None, [self.system], {'S': 'table0.C1', 'S.name': 'table0.C0', 'SN': 'table0.C0'}, |
1257 None, None, [self.system], {'S': 'table0.C1', 'S.name': 'table0.C0', 'SN': 'table0.C0'}, |
1258 []),] |
1258 []),] |
1259 )]) |
1259 )]) |
1260 |
1260 |
1261 def test_external_attributes_and_relation(self): |
1261 def test_external_attributes_and_relation(self): |
1262 repo._type_source_cache[999999] = ('Note', 'cards', 999999) |
1262 repo._type_source_cache[999999] = ('Note', 'cards', 999999) |
1263 self._test('Any A,B,C,D WHERE A eid %(x)s,A creation_date B,A modification_date C, A todo_by D?', |
1263 self._test('Any A,B,C,D WHERE A eid %(x)s,A creation_date B,A modification_date C, A todo_by D?', |
1264 [('FetchStep', [('Any A,B,C WHERE A eid 999999, A creation_date B, A modification_date C, A is Note', |
1264 [('FetchStep', [('Any A,B,C WHERE A eid 999999, A creation_date B, A modification_date C, A is Note', |
1265 [{'A': 'Note', 'C': 'Datetime', 'B': 'Datetime'}])], |
1265 [{'A': 'Note', 'C': 'Datetime', 'B': 'Datetime'}])], |
1300 ('OneFetchStep', [(u'Any X WHERE X has_text "toto", X title "zoubidou", X is EmailThread', |
1300 ('OneFetchStep', [(u'Any X WHERE X has_text "toto", X title "zoubidou", X is EmailThread', |
1301 [{'X': 'EmailThread'}])], |
1301 [{'X': 'EmailThread'}])], |
1302 None, None, [self.system], {}, []), |
1302 None, None, [self.system], {}, []), |
1303 ]), |
1303 ]), |
1304 ]) |
1304 ]) |
1305 |
1305 |
1306 def test_sort_func(self): |
1306 def test_sort_func(self): |
1307 self._test('Note X ORDERBY DUMB_SORT(RF) WHERE X type RF', |
1307 self._test('Note X ORDERBY DUMB_SORT(RF) WHERE X type RF', |
1308 [('AggrStep', 'Any X ORDERBY DUMB_SORT(RF)', None, None, 'table0', None, [ |
1308 [('AggrStep', 'Any X ORDERBY DUMB_SORT(RF)', None, None, 'table0', None, [ |
1309 ('FetchStep', [('Any X,RF WHERE X type RF, X is Note', |
1309 ('FetchStep', [('Any X,RF WHERE X type RF, X is Note', |
1310 [{'X': 'Note', 'RF': 'String'}])], |
1310 [{'X': 'Note', 'RF': 'String'}])], |
1469 ], |
1469 ], |
1470 {'x': 999999,}) |
1470 {'x': 999999,}) |
1471 |
1471 |
1472 def test_crossed_relation_eid_2_needattr(self): |
1472 def test_crossed_relation_eid_2_needattr(self): |
1473 repo._type_source_cache[999999] = ('Note', 'cards', 999999) |
1473 repo._type_source_cache[999999] = ('Note', 'cards', 999999) |
1474 self._test('Any Y,T WHERE X eid %(x)s, X multisource_crossed_rel Y, Y type T', |
1474 self._test('Any Y,T WHERE X eid %(x)s, X multisource_crossed_rel Y, Y type T', |
1475 [('FetchStep', [('Any Y,T WHERE Y type T, Y is Note', [{'T': 'String', 'Y': 'Note'}])], |
1475 [('FetchStep', [('Any Y,T WHERE Y type T, Y is Note', [{'T': 'String', 'Y': 'Note'}])], |
1476 [self.rql, self.system], None, |
1476 [self.rql, self.system], None, |
1477 {'T': 'table0.C1', 'Y': 'table0.C0', 'Y.type': 'table0.C1'}, []), |
1477 {'T': 'table0.C1', 'Y': 'table0.C0', 'Y.type': 'table0.C1'}, []), |
1478 ('UnionStep', None, None, |
1478 ('UnionStep', None, None, |
1479 [('OneFetchStep', [('Any Y,T WHERE 999999 multisource_crossed_rel Y, Y type T, Y is Note', |
1479 [('OneFetchStep', [('Any Y,T WHERE 999999 multisource_crossed_rel Y, Y type T, Y is Note', |
1600 [{'A': 'Affaire'}])], |
1600 [{'A': 'Affaire'}])], |
1601 None, None, [self.system], {}, [])] |
1601 None, None, [self.system], {}, [])] |
1602 )] |
1602 )] |
1603 )], |
1603 )], |
1604 {'n': 999999, 's': 999998}) |
1604 {'n': 999999, 's': 999998}) |
1605 |
1605 |
1606 def test_delete_relation1(self): |
1606 def test_delete_relation1(self): |
1607 ueid = self.session.user.eid |
1607 ueid = self.session.user.eid |
1608 self._test('DELETE X created_by Y WHERE X eid %(x)s, NOT Y eid %(y)s', |
1608 self._test('DELETE X created_by Y WHERE X eid %(x)s, NOT Y eid %(y)s', |
1609 [('DeleteRelationsStep', [ |
1609 [('DeleteRelationsStep', [ |
1610 ('OneFetchStep', [('Any 5,Y WHERE %s created_by Y, NOT Y eid %s, Y is CWUser'%(ueid, ueid), |
1610 ('OneFetchStep', [('Any 5,Y WHERE %s created_by Y, NOT Y eid %s, Y is CWUser'%(ueid, ueid), |
1611 [{'Y': 'CWUser'}])], |
1611 [{'Y': 'CWUser'}])], |
1612 None, None, [self.system], {}, []), |
1612 None, None, [self.system], {}, []), |
1613 ]), |
1613 ]), |
1614 ], |
1614 ], |
1615 {'x': ueid, 'y': ueid}) |
1615 {'x': ueid, 'y': ueid}) |
1616 |
1616 |
1617 def test_delete_relation2(self): |
1617 def test_delete_relation2(self): |
1618 ueid = self.session.user.eid |
1618 ueid = self.session.user.eid |
1619 self._test('DELETE X created_by Y WHERE X eid %(x)s, NOT Y login "syt"', |
1619 self._test('DELETE X created_by Y WHERE X eid %(x)s, NOT Y login "syt"', |
1620 [('FetchStep', [('Any Y WHERE NOT Y login "syt", Y is CWUser', [{'Y': 'CWUser'}])], |
1620 [('FetchStep', [('Any Y WHERE NOT Y login "syt", Y is CWUser', [{'Y': 'CWUser'}])], |
1621 [self.ldap, self.system], None, {'Y': 'table0.C0'}, []), |
1621 [self.ldap, self.system], None, {'Y': 'table0.C0'}, []), |
1634 [{'Y': 'Card'}, {'Y': 'Note'}])], |
1634 [{'Y': 'Card'}, {'Y': 'Note'}])], |
1635 None, None, [self.system], {}, []) |
1635 None, None, [self.system], {}, []) |
1636 ]) |
1636 ]) |
1637 ], |
1637 ], |
1638 {'x': 999999}) |
1638 {'x': 999999}) |
1639 |
1639 |
1640 def test_delete_entity2(self): |
1640 def test_delete_entity2(self): |
1641 repo._type_source_cache[999999] = ('Note', 'system', 999999) |
1641 repo._type_source_cache[999999] = ('Note', 'system', 999999) |
1642 self._test('DELETE Note X WHERE X eid %(x)s, NOT X multisource_inlined_rel Y', |
1642 self._test('DELETE Note X WHERE X eid %(x)s, NOT X multisource_inlined_rel Y', |
1643 [('DeleteEntitiesStep', |
1643 [('DeleteEntitiesStep', |
1644 [('OneFetchStep', [('Any X WHERE X eid 999999, NOT X multisource_inlined_rel Y, X is Note, Y is IN(Affaire, Note)', |
1644 [('OneFetchStep', [('Any X WHERE X eid 999999, NOT X multisource_inlined_rel Y, X is Note, Y is IN(Affaire, Note)', |
1645 [{'X': 'Note', 'Y': 'Affaire'}, {'X': 'Note', 'Y': 'Note'}])], |
1645 [{'X': 'Note', 'Y': 'Affaire'}, {'X': 'Note', 'Y': 'Note'}])], |
1646 None, None, [self.system], {}, []) |
1646 None, None, [self.system], {}, []) |
1647 ]) |
1647 ]) |
1648 ], |
1648 ], |
1649 {'x': 999999}) |
1649 {'x': 999999}) |
1650 |
1650 |
1651 def test_update(self): |
1651 def test_update(self): |
1652 self._test('SET X copain Y WHERE X login "comme", Y login "cochon"', |
1652 self._test('SET X copain Y WHERE X login "comme", Y login "cochon"', |
1653 [('FetchStep', |
1653 [('FetchStep', |
1654 [('Any X WHERE X login "comme", X is CWUser', [{'X': 'CWUser'}])], |
1654 [('Any X WHERE X login "comme", X is CWUser', [{'X': 'CWUser'}])], |
1655 [self.ldap, self.system], None, {'X': 'table0.C0'}, []), |
1655 [self.ldap, self.system], None, {'X': 'table0.C0'}, []), |
1699 # ('OneFetchStep', [('DISTINCT Any X,%s WHERE X is CWUser' % activatedeid, |
1699 # ('OneFetchStep', [('DISTINCT Any X,%s WHERE X is CWUser' % activatedeid, |
1700 # [{'X': 'CWUser'}])], |
1700 # [{'X': 'CWUser'}])], |
1701 # None, None, [self.system], {}, []), |
1701 # None, None, [self.system], {}, []), |
1702 # ]), |
1702 # ]), |
1703 # ]) |
1703 # ]) |
1704 |
1704 |
1705 # non regression tests #################################################### |
1705 # non regression tests #################################################### |
1706 |
1706 |
1707 def test_nonregr1(self): |
1707 def test_nonregr1(self): |
1708 self._test('Any X, Y WHERE X copain Y, X login "syt", Y login "cochon"', |
1708 self._test('Any X, Y WHERE X copain Y, X login "syt", Y login "cochon"', |
1709 [('FetchStep', |
1709 [('FetchStep', |
1710 [('Any X WHERE X login "syt", X is CWUser', [{'X': 'CWUser'}])], |
1710 [('Any X WHERE X login "syt", X is CWUser', [{'X': 'CWUser'}])], |
1711 [self.ldap, self.system], None, {'X': 'table0.C0'}, []), |
1711 [self.ldap, self.system], None, {'X': 'table0.C0'}, []), |
1715 ('OneFetchStep', |
1715 ('OneFetchStep', |
1716 [('Any X,Y WHERE X copain Y, X is CWUser, Y is CWUser', |
1716 [('Any X,Y WHERE X copain Y, X is CWUser, Y is CWUser', |
1717 [{'X': 'CWUser', 'Y': 'CWUser'}])], |
1717 [{'X': 'CWUser', 'Y': 'CWUser'}])], |
1718 None, None, [self.system], {'X': 'table0.C0', 'Y': 'table1.C0'}, []) |
1718 None, None, [self.system], {'X': 'table0.C0', 'Y': 'table1.C0'}, []) |
1719 ]) |
1719 ]) |
1720 |
1720 |
1721 def test_nonregr2(self): |
1721 def test_nonregr2(self): |
1722 treid = self.session.user.latest_trinfo().eid |
1722 treid = self.session.user.latest_trinfo().eid |
1723 self._test('Any X ORDERBY D DESC WHERE E eid %(x)s, E wf_info_for X, X modification_date D', |
1723 self._test('Any X ORDERBY D DESC WHERE E eid %(x)s, E wf_info_for X, X modification_date D', |
1724 [('FetchStep', [('Any X,D WHERE X modification_date D, X is Note', |
1724 [('FetchStep', [('Any X,D WHERE X modification_date D, X is Note', |
1725 [{'X': 'Note', 'D': 'Datetime'}])], |
1725 [{'X': 'Note', 'D': 'Datetime'}])], |
1744 {'X': 'table0.C0', 'X.modification_date': 'table0.C1', 'D': 'table0.C1'}, |
1744 {'X': 'table0.C0', 'X.modification_date': 'table0.C1', 'D': 'table0.C1'}, |
1745 {'X': 'table2.C0', 'X.modification_date': 'table2.C1', 'D': 'table2.C1', 'E.wf_info_for': 'table2.C0'}, []), |
1745 {'X': 'table2.C0', 'X.modification_date': 'table2.C1', 'D': 'table2.C1', 'E.wf_info_for': 'table2.C0'}, []), |
1746 ]), |
1746 ]), |
1747 ], |
1747 ], |
1748 {'x': treid}) |
1748 {'x': treid}) |
1749 |
1749 |
1750 def test_nonregr3(self): |
1750 def test_nonregr3(self): |
1751 # original jpl query: |
1751 # original jpl query: |
1752 # Any X, NOW - CD, P WHERE P is Project, U interested_in P, U is CWUser, U login "sthenault", X concerns P, X creation_date CD ORDERBY CD DESC LIMIT 5 |
1752 # Any X, NOW - CD, P WHERE P is Project, U interested_in P, U is CWUser, U login "sthenault", X concerns P, X creation_date CD ORDERBY CD DESC LIMIT 5 |
1753 self._test('Any X, NOW - CD, P ORDERBY CD DESC LIMIT 5 WHERE P bookmarked_by U, U login "admin", P is X, X creation_date CD', |
1753 self._test('Any X, NOW - CD, P ORDERBY CD DESC LIMIT 5 WHERE P bookmarked_by U, U login "admin", P is X, X creation_date CD', |
1754 [('FetchStep', [('Any U WHERE U login "admin", U is CWUser', [{'U': 'CWUser'}])], |
1754 [('FetchStep', [('Any U WHERE U login "admin", U is CWUser', [{'U': 'CWUser'}])], |
1755 [self.ldap, self.system], None, {'U': 'table0.C0'}, []), |
1755 [self.ldap, self.system], None, {'U': 'table0.C0'}, []), |
1756 ('OneFetchStep', [('Any X,(NOW - CD),P ORDERBY CD DESC LIMIT 5 WHERE P bookmarked_by U, P is X, X creation_date CD, P is Bookmark, U is CWUser, X is CWEType', |
1756 ('OneFetchStep', [('Any X,(NOW - CD),P ORDERBY CD DESC LIMIT 5 WHERE P bookmarked_by U, P is X, X creation_date CD, P is Bookmark, U is CWUser, X is CWEType', |
1757 [{'P': 'Bookmark', 'U': 'CWUser', 'X': 'CWEType', 'CD': 'Datetime'}])], |
1757 [{'P': 'Bookmark', 'U': 'CWUser', 'X': 'CWEType', 'CD': 'Datetime'}])], |
1758 5, None, [self.system], {'U': 'table0.C0'}, [])] |
1758 5, None, [self.system], {'U': 'table0.C0'}, [])] |
1759 ) |
1759 ) |
1760 |
1760 |
1761 def test_nonregr4(self): |
1761 def test_nonregr4(self): |
1762 self._test('Any U ORDERBY D DESC WHERE WF wf_info_for X, WF creation_date D, WF from_state FS, ' |
1762 self._test('Any U ORDERBY D DESC WHERE WF wf_info_for X, WF creation_date D, WF from_state FS, ' |
1763 'WF owned_by U?, X eid %(x)s', |
1763 'WF owned_by U?, X eid %(x)s', |
1764 [#('FetchStep', [('Any U WHERE U is CWUser', [{'U': 'CWUser'}])], |
1764 [#('FetchStep', [('Any U WHERE U is CWUser', [{'U': 'CWUser'}])], |
1765 # [self.ldap, self.system], None, {'U': 'table0.C0'}, []), |
1765 # [self.ldap, self.system], None, {'U': 'table0.C0'}, []), |
1769 [self.system], {}, [])], |
1769 [self.system], {}, [])], |
1770 {'x': self.session.user.eid}) |
1770 {'x': self.session.user.eid}) |
1771 |
1771 |
1772 def test_nonregr5(self): |
1772 def test_nonregr5(self): |
1773 # original jpl query: |
1773 # original jpl query: |
1774 # DISTINCT Version V WHERE MB done_in MV, MV eid %(x)s, |
1774 # DISTINCT Version V WHERE MB done_in MV, MV eid %(x)s, |
1775 # MB depends_on B, B done_in V, V version_of P, NOT P eid %(p)s' |
1775 # MB depends_on B, B done_in V, V version_of P, NOT P eid %(p)s' |
1776 cardeid = self.execute('INSERT Card X: X title "hop"')[0][0] |
1776 cardeid = self.execute('INSERT Card X: X title "hop"')[0][0] |
1777 noteeid = self.execute('INSERT Note X')[0][0] |
1777 noteeid = self.execute('INSERT Note X')[0][0] |
1778 self._test('DISTINCT Card V WHERE MB documented_by MV, MV eid %(x)s, ' |
1778 self._test('DISTINCT Card V WHERE MB documented_by MV, MV eid %(x)s, ' |
1779 'MB depends_on B, B documented_by V, V multisource_rel P, NOT P eid %(p)s', |
1779 'MB depends_on B, B documented_by V, V multisource_rel P, NOT P eid %(p)s', |
1820 [self.rql], None, {}, []), |
1820 [self.rql], None, {}, []), |
1821 ('OneFetchStep', [('Any 999999,Z WHERE Z concerne 999999, Z is Affaire', |
1821 ('OneFetchStep', [('Any 999999,Z WHERE Z concerne 999999, Z is Affaire', |
1822 [{'Z': 'Affaire'}])], |
1822 [{'Z': 'Affaire'}])], |
1823 None, None, [self.system], {}, [])], |
1823 None, None, [self.system], {}, [])], |
1824 {'x': 999999}) |
1824 {'x': 999999}) |
1825 |
1825 |
1826 def test_nonregr9(self): |
1826 def test_nonregr9(self): |
1827 repo._type_source_cache[999999] = ('Note', 'cards', 999999) |
1827 repo._type_source_cache[999999] = ('Note', 'cards', 999999) |
1828 repo._type_source_cache[999998] = ('Note', 'cards', 999998) |
1828 repo._type_source_cache[999998] = ('Note', 'cards', 999998) |
1829 self._test('SET X migrated_from Y WHERE X eid %(x)s, Y multisource_rel Z, Z eid %(z)s, Y migrated_from Z', |
1829 self._test('SET X migrated_from Y WHERE X eid %(x)s, Y multisource_rel Z, Z eid %(z)s, Y migrated_from Z', |
1830 [('FetchStep', [('Any Y WHERE Y multisource_rel 999998, Y is Note', [{'Y': 'Note'}])], |
1830 [('FetchStep', [('Any Y WHERE Y multisource_rel 999998, Y is Note', [{'Y': 'Note'}])], |