307 eschema = self._schema.eschema |
307 eschema = self._schema.eschema |
308 sourcesterms = self._sourcesterms |
308 sourcesterms = self._sourcesterms |
309 # find for each source which variable/solution are supported |
309 # find for each source which variable/solution are supported |
310 for varname, varobj in self.rqlst.defined_vars.items(): |
310 for varname, varobj in self.rqlst.defined_vars.items(): |
311 # if variable has an eid specified, we can get its source directly |
311 # if variable has an eid specified, we can get its source directly |
312 # NOTE: use uidrels and not constnode to deal with "X eid IN(1,2,3,4)" |
312 # NOTE: use uidrel and not constnode to deal with "X eid IN(1,2,3,4)" |
313 if varobj.stinfo['uidrels']: |
313 if varobj.stinfo['uidrel'] is not None: |
314 vrels = varobj.stinfo['relations'] - varobj.stinfo['uidrels'] |
314 rel = varobj.stinfo['uidrel'] |
315 for rel in varobj.stinfo['uidrels']: |
315 for const in rel.children[1].get_nodes(Constant): |
316 for const in rel.children[1].get_nodes(Constant): |
316 eid = const.eval(self.plan.args) |
317 eid = const.eval(self.plan.args) |
317 source = self._session.source_from_eid(eid) |
318 source = self._session.source_from_eid(eid) |
318 if vrels and not any(source.support_relation(r.r_type) |
319 if vrels and not any(source.support_relation(r.r_type) |
319 for r in vrels if not r is rel): |
320 for r in vrels): |
320 self._set_source_for_term(self.system_source, varobj) |
321 self._set_source_for_term(self.system_source, varobj) |
321 else: |
322 else: |
322 self._set_source_for_term(source, varobj) |
323 self._set_source_for_term(source, varobj) |
|
324 continue |
323 continue |
325 rels = varobj.stinfo['relations'] |
324 rels = varobj.stinfo['relations'] |
326 if not rels and not varobj.stinfo['typerels']: |
325 if not rels and varobj.stinfo['typerel'] is None: |
327 # (rare) case where the variable has no type specified nor |
326 # (rare) case where the variable has no type specified nor |
328 # relation accessed ex. "Any MAX(X)" |
327 # relation accessed ex. "Any MAX(X)" |
329 self._set_source_for_term(self.system_source, varobj) |
328 self._set_source_for_term(self.system_source, varobj) |
330 continue |
329 continue |
331 for i, sol in enumerate(self._solutions): |
330 for i, sol in enumerate(self._solutions): |
698 # add attribute variables and mark variables which should be |
697 # add attribute variables and mark variables which should be |
699 # additionaly selected when possible |
698 # additionaly selected when possible |
700 for var in select.defined_vars.itervalues(): |
699 for var in select.defined_vars.itervalues(): |
701 if not var in terms: |
700 if not var in terms: |
702 stinfo = var.stinfo |
701 stinfo = var.stinfo |
703 for ovar, rtype in stinfo['attrvars']: |
702 for ovar, rtype in stinfo.get('attrvars', ()): |
704 if ovar in terms: |
703 if ovar in terms: |
705 needsel.add(var.name) |
704 needsel.add(var.name) |
706 terms.append(var) |
705 terms.append(var) |
707 break |
706 break |
708 else: |
707 else: |
776 # supported relation with at least one end supported, check the |
775 # supported relation with at least one end supported, check the |
777 # other end is in as well. If not this usually means the |
776 # other end is in as well. If not this usually means the |
778 # variable is refed by an outer scope and should be substituted |
777 # variable is refed by an outer scope and should be substituted |
779 # using an 'identity' relation (else we'll get a conflict of |
778 # using an 'identity' relation (else we'll get a conflict of |
780 # temporary tables) |
779 # temporary tables) |
781 if rhsvar in terms and not lhsvar in terms: |
780 if rhsvar in terms and not lhsvar in terms and lhsvar.scope is lhsvar.stmt: |
782 self._identity_substitute(rel, lhsvar, terms, needsel) |
781 self._identity_substitute(rel, lhsvar, terms, needsel) |
783 elif lhsvar in terms and not rhsvar in terms: |
782 elif lhsvar in terms and not rhsvar in terms and rhsvar.scope is rhsvar.stmt: |
784 self._identity_substitute(rel, rhsvar, terms, needsel) |
783 self._identity_substitute(rel, rhsvar, terms, needsel) |
785 |
784 |
786 def _identity_substitute(self, relation, var, terms, needsel): |
785 def _identity_substitute(self, relation, var, terms, needsel): |
787 newvar = self._insert_identity_variable(relation.scope, var) |
786 newvar = self._insert_identity_variable(relation.scope, var) |
788 if newvar is not None: |
787 # ensure relation is using '=' operator, else we rely on a |
789 # ensure relation is using '=' operator, else we rely on a |
788 # sqlgenerator side effect (it won't insert an inequality operator |
790 # sqlgenerator side effect (it won't insert an inequality operator |
789 # in this case) |
791 # in this case) |
790 relation.children[1].operator = '=' |
792 relation.children[1].operator = '=' |
791 terms.append(newvar) |
793 terms.append(newvar) |
792 needsel.add(newvar.name) |
794 needsel.add(newvar.name) |
|
795 |
793 |
796 def _choose_term(self, sourceterms): |
794 def _choose_term(self, sourceterms): |
797 """pick one term among terms supported by a source, which will be used |
795 """pick one term among terms supported by a source, which will be used |
798 as a base to generate an execution step |
796 as a base to generate an execution step |
799 """ |
797 """ |
1416 return False |
1414 return False |
1417 if var.name in self.extneedsel or var.stinfo['selected']: |
1415 if var.name in self.extneedsel or var.stinfo['selected']: |
1418 return False |
1416 return False |
1419 if not var in terms or used_in_outer_scope(var, self.current_scope): |
1417 if not var in terms or used_in_outer_scope(var, self.current_scope): |
1420 return False |
1418 return False |
1421 if any(v for v, _ in var.stinfo['attrvars'] if not v in terms): |
1419 if any(v for v, _ in var.stinfo.get('attrvars', ()) if not v in terms): |
1422 return False |
1420 return False |
1423 return True |
1421 return True |
1424 |
1422 |
1425 def visit_exists(self, node, newroot, terms): |
1423 def visit_exists(self, node, newroot, terms): |
1426 newexists = node.__class__() |
1424 newexists = node.__class__() |