52 try: |
52 try: |
53 var = newroot.defined_vars[varname] |
53 var = newroot.defined_vars[varname] |
54 except KeyError: |
54 except KeyError: |
55 continue |
55 continue |
56 stinfo = var.stinfo |
56 stinfo = var.stinfo |
57 if stinfo.get('uidrels'): |
57 if stinfo.get('uidrel') is not None: |
58 continue # eid specified, no need for additional type specification |
58 continue # eid specified, no need for additional type specification |
59 try: |
59 try: |
60 typerels = rqlst.defined_vars[varname].stinfo.get('typerels') |
60 typerel = rqlst.defined_vars[varname].stinfo.get('typerel') |
61 except KeyError: |
61 except KeyError: |
62 assert varname in rqlst.aliases |
62 assert varname in rqlst.aliases |
63 continue |
63 continue |
64 if newroot is rqlst and typerels: |
64 if newroot is rqlst and typerel is not None: |
65 mytyperel = iter(typerels).next() |
65 mytyperel = typerel |
66 else: |
66 else: |
67 for vref in newroot.defined_vars[varname].references(): |
67 for vref in newroot.defined_vars[varname].references(): |
68 rel = vref.relation() |
68 rel = vref.relation() |
69 if rel and rel.is_types_restriction(): |
69 if rel and rel.is_types_restriction(): |
70 mytyperel = rel |
70 mytyperel = rel |
91 rel = var.scope.add_type_restriction(var, possibletypes) |
91 rel = var.scope.add_type_restriction(var, possibletypes) |
92 else: |
92 else: |
93 # tree is not annotated yet, no scope set so add the restriction |
93 # tree is not annotated yet, no scope set so add the restriction |
94 # to the root |
94 # to the root |
95 rel = newroot.add_type_restriction(var, possibletypes) |
95 rel = newroot.add_type_restriction(var, possibletypes) |
96 stinfo['typerels'] = frozenset((rel,)) |
96 stinfo['typerel'] = rel |
97 stinfo['possibletypes'] = possibletypes |
97 stinfo['possibletypes'] = possibletypes |
98 |
98 |
99 |
99 |
100 def remove_solutions(origsolutions, solutions, defined): |
100 def remove_solutions(origsolutions, solutions, defined): |
101 """when a rqlst has been generated from another by introducing security |
101 """when a rqlst has been generated from another by introducing security |
153 def rewrite(self, select, snippets, solutions, kwargs, existingvars=None): |
153 def rewrite(self, select, snippets, solutions, kwargs, existingvars=None): |
154 """ |
154 """ |
155 snippets: (varmap, list of rql expression) |
155 snippets: (varmap, list of rql expression) |
156 with varmap a *tuple* (select var, snippet var) |
156 with varmap a *tuple* (select var, snippet var) |
157 """ |
157 """ |
158 self.select = self.insert_scope = select |
158 self.select = select |
159 self.solutions = solutions |
159 self.solutions = solutions |
160 self.kwargs = kwargs |
160 self.kwargs = kwargs |
161 self.u_varname = None |
161 self.u_varname = None |
162 self.removing_ambiguity = False |
162 self.removing_ambiguity = False |
163 self.exists_snippet = {} |
163 self.exists_snippet = {} |
164 self.pending_keys = [] |
164 self.pending_keys = [] |
165 self.existingvars = existingvars |
165 self.existingvars = existingvars |
|
166 self._insert_scope = None |
166 # we have to annotate the rqlst before inserting snippets, even though |
167 # we have to annotate the rqlst before inserting snippets, even though |
167 # we'll have to redo it latter |
168 # we'll have to redo it latter |
168 self.annotate(select) |
169 self.annotate(select) |
169 self.insert_snippets(snippets) |
170 self.insert_snippets(snippets) |
170 if not self.exists_snippet and self.u_varname: |
171 if not self.exists_snippet and self.u_varname: |
247 finally: |
248 finally: |
248 self.existingvars = existing |
249 self.existingvars = existing |
249 |
250 |
250 def _insert_snippet(self, varmap, parent, new): |
251 def _insert_snippet(self, varmap, parent, new): |
251 if new is not None: |
252 if new is not None: |
|
253 if self._insert_scope is None: |
|
254 insert_scope = self.varinfo.get('stinfo', {}).get('scope', self.select) |
|
255 else: |
|
256 insert_scope = self._insert_scope |
252 if self.varinfo.get('stinfo', {}).get('optrelations'): |
257 if self.varinfo.get('stinfo', {}).get('optrelations'): |
253 assert parent is None |
258 assert parent is None |
254 self.insert_scope = self.snippet_subquery(varmap, new) |
259 self._insert_scope = self.snippet_subquery(varmap, new) |
255 self.insert_pending() |
260 self.insert_pending() |
256 self.insert_scope = self.select |
261 self._insert_scope = None |
257 return |
262 return |
258 new = n.Exists(new) |
263 new = n.Exists(new) |
259 if parent is None: |
264 if parent is None: |
260 self.insert_scope.add_restriction(new) |
265 insert_scope.add_restriction(new) |
261 else: |
266 else: |
262 grandpa = parent.parent |
267 grandpa = parent.parent |
263 or_ = n.Or(parent, new) |
268 or_ = n.Or(parent, new) |
264 grandpa.replace(parent, or_) |
269 grandpa.replace(parent, or_) |
265 if not self.removing_ambiguity: |
270 if not self.removing_ambiguity: |
272 else: |
277 else: |
273 parent.parent.replace(or_, or_.children[0]) |
278 parent.parent.replace(or_, or_.children[0]) |
274 self._cleanup_inserted(new) |
279 self._cleanup_inserted(new) |
275 raise |
280 raise |
276 else: |
281 else: |
277 self.insert_scope = new |
282 self._insert_scope = new |
278 self.insert_pending() |
283 self.insert_pending() |
279 self.insert_scope = self.select |
284 self._insert_scope = None |
280 return new |
285 return new |
281 self.insert_pending() |
286 self.insert_pending() |
282 |
287 |
283 def insert_pending(self): |
288 def insert_pending(self): |
284 """pending_keys hold variable referenced by U has_<action>_permission X |
289 """pending_keys hold variable referenced by U has_<action>_permission X |
346 if rschema.inlined and rel.optional: |
351 if rschema.inlined and rel.optional: |
347 need_null_test = True |
352 need_null_test = True |
348 if need_null_test: |
353 if need_null_test: |
349 snippetrqlst = n.Or( |
354 snippetrqlst = n.Or( |
350 n.make_relation(subselectvar, 'is', (None, None), n.Constant, |
355 n.make_relation(subselectvar, 'is', (None, None), n.Constant, |
351 operator='IS'), |
356 operator='='), |
352 snippetrqlst) |
357 snippetrqlst) |
353 subselect.add_restriction(snippetrqlst) |
358 subselect.add_restriction(snippetrqlst) |
354 if self.u_varname: |
359 if self.u_varname: |
355 # generate an identifier for the substitution |
360 # generate an identifier for the substitution |
356 argname = subselect.allocate_varname() |
361 argname = subselect.allocate_varname() |