302 |
302 |
303 def snippet_subquery(self, varmap, transformedsnippet): |
303 def snippet_subquery(self, varmap, transformedsnippet): |
304 """introduce the given snippet in a subquery""" |
304 """introduce the given snippet in a subquery""" |
305 subselect = stmts.Select() |
305 subselect = stmts.Select() |
306 selectvar = varmap[0] |
306 selectvar = varmap[0] |
307 subselect.append_selected(n.VariableRef( |
307 subselectvar = subselect.get_variable(selectvar) |
308 subselect.get_variable(selectvar))) |
308 subselect.append_selected(n.VariableRef(subselectvar)) |
|
309 snippetrqlst = n.Exists(transformedsnippet.copy(subselect)) |
309 aliases = [selectvar] |
310 aliases = [selectvar] |
310 subselect.add_restriction(transformedsnippet.copy(subselect)) |
|
311 stinfo = self.varinfo['stinfo'] |
311 stinfo = self.varinfo['stinfo'] |
|
312 need_null_test = False |
312 for rel in stinfo['relations']: |
313 for rel in stinfo['relations']: |
313 rschema = self.schema.rschema(rel.r_type) |
314 rschema = self.schema.rschema(rel.r_type) |
314 if rschema.final or (rschema.inlined and |
315 if rschema.final or (rschema.inlined and |
315 not rel in stinfo['rhsrelations']): |
316 not rel in stinfo['rhsrelations']): |
316 self.select.remove_node(rel) |
317 rel.children[0].name = selectvar # XXX explain why |
317 rel.children[0].name = selectvar |
|
318 subselect.add_restriction(rel.copy(subselect)) |
318 subselect.add_restriction(rel.copy(subselect)) |
319 for vref in rel.children[1].iget_nodes(n.VariableRef): |
319 for vref in rel.children[1].iget_nodes(n.VariableRef): |
320 subselect.append_selected(vref.copy(subselect)) |
320 subselect.append_selected(vref.copy(subselect)) |
321 aliases.append(vref.name) |
321 aliases.append(vref.name) |
|
322 self.select.remove_node(rel) |
|
323 # when some inlined relation has to be copied in the subquery, |
|
324 # we need to test that either value is NULL or that the snippet |
|
325 # condition is satisfied |
|
326 if rschema.inlined and rel.optional: |
|
327 need_null_test = True |
|
328 if need_null_test: |
|
329 snippetrqlst = n.Or( |
|
330 n.make_relation(subselectvar, 'is', (None, None), n.Constant, |
|
331 operator='IS'), |
|
332 snippetrqlst) |
|
333 subselect.add_restriction(snippetrqlst) |
322 if self.u_varname: |
334 if self.u_varname: |
323 # generate an identifier for the substitution |
335 # generate an identifier for the substitution |
324 argname = subselect.allocate_varname() |
336 argname = subselect.allocate_varname() |
325 while argname in self.kwargs: |
337 while argname in self.kwargs: |
326 argname = subselect.allocate_varname() |
338 argname = subselect.allocate_varname() |