342 self.needsplit = True |
342 self.needsplit = True |
343 # add source for rewritten constants to sourcesterms |
343 # add source for rewritten constants to sourcesterms |
344 for vconsts in self.rqlst.stinfo['rewritten'].itervalues(): |
344 for vconsts in self.rqlst.stinfo['rewritten'].itervalues(): |
345 const = vconsts[0] |
345 const = vconsts[0] |
346 source = self._session.source_from_eid(const.eval(self.plan.args)) |
346 source = self._session.source_from_eid(const.eval(self.plan.args)) |
347 if source is self._repo.system_source: |
347 if source is repo.system_source: |
348 for const in vconsts: |
348 for const in vconsts: |
349 self._set_source_for_term(source, const) |
349 self._set_source_for_term(source, const) |
350 elif source in self._sourcesterms: |
350 elif source in self._sourcesterms: |
351 source_scopes = frozenset(t.scope for t in self._sourcesterms[source]) |
351 source_scopes = frozenset(t.scope for t in self._sourcesterms[source]) |
352 for const in vconsts: |
352 for const in vconsts: |
353 if const.scope in source_scopes: |
353 if const.scope in source_scopes: |
354 self._set_source_for_term(source, const) |
354 self._set_source_for_term(source, const) |
|
355 # if system source is used, add every rewritten constant |
|
356 # to its supported terms even when associated entity |
|
357 # doesn't actually comes from it so we get a changes |
|
358 # that allequals will return True as expected when |
|
359 # computing needsplit |
|
360 if repo.system_source in sourcesterms: |
|
361 self._set_source_for_term(repo.system_source, const) |
355 # add source for relations |
362 # add source for relations |
356 rschema = self._schema.rschema |
363 rschema = self._schema.rschema |
357 termssources = {} |
364 termssources = {} |
358 for rel in self.rqlst.iget_nodes(Relation): |
365 for rel in self.rqlst.iget_nodes(Relation): |
359 # process non final relations only |
366 # process non final relations only |
397 crossvars = set(x.variable for x in rel.get_nodes(VariableRef)) |
404 crossvars = set(x.variable for x in rel.get_nodes(VariableRef)) |
398 for const in rel.get_nodes(Constant): |
405 for const in rel.get_nodes(Constant): |
399 if source.uri != 'system' and not const in self._sourcesterms.get(source, ()): |
406 if source.uri != 'system' and not const in self._sourcesterms.get(source, ()): |
400 continue |
407 continue |
401 crossvars.add(const) |
408 crossvars.add(const) |
402 # XXX this is counter intuitive, though this is currently a |
|
403 # trick to add const to system source terms so we get a |
|
404 # chance that solutions will compare to equals when |
|
405 # computing need split |
|
406 allsols = set(self._solindices) |
|
407 try: |
|
408 self._sourcesterms[ssource][const] = allsols |
|
409 except KeyError: |
|
410 self._sourcesterms[ssource] = {const: allsols} |
|
411 self._crossrelations.setdefault(source, {})[rel] = crossvars |
409 self._crossrelations.setdefault(source, {})[rel] = crossvars |
412 if len(crossvars) < 2: |
410 if len(crossvars) < 2: |
413 # this means there is a constant in the relation which is |
411 # this means there is a constant in the relation which is |
414 # not supported by the source, so we can stop here |
412 # not supported by the source, so we can stop here |
415 continue |
413 continue |
515 norelsup = self._norel_support_set(rel) |
513 norelsup = self._norel_support_set(rel) |
516 termsources = termssources[term] |
514 termsources = termssources[term] |
517 invalid_sources = termsources - (termssources[oterm] | norelsup) |
515 invalid_sources = termsources - (termssources[oterm] | norelsup) |
518 if invalid_sources and self._repo.can_cross_relation(rel.r_type): |
516 if invalid_sources and self._repo.can_cross_relation(rel.r_type): |
519 invalid_sources -= self._sys_source_set |
517 invalid_sources -= self._sys_source_set |
520 if invalid_sources and isinstance(term, Variable) and self._need_ext_source_access(term, rel): |
518 if invalid_sources and isinstance(term, Variable) \ |
|
519 and self._need_ext_source_access(term, rel): |
521 # if the term is a not invariant variable, we should filter out |
520 # if the term is a not invariant variable, we should filter out |
522 # source where the relation is a cross relation from invalid |
521 # source where the relation is a cross relation from invalid |
523 # sources |
522 # sources |
524 invalid_sources = frozenset([(s, solidx) for s, solidx in invalid_sources |
523 invalid_sources = frozenset([(s, solidx) for s, solidx in invalid_sources |
525 if not (s in self._crossrelations and |
524 if not (s in self._crossrelations and |
561 # multi-sources relation |
560 # multi-sources relation |
562 if self._crossrelations: |
561 if self._crossrelations: |
563 for reldict in self._crossrelations.itervalues(): |
562 for reldict in self._crossrelations.itervalues(): |
564 for rel, terms in reldict.iteritems(): |
563 for rel, terms in reldict.iteritems(): |
565 for term in terms: |
564 for term in terms: |
566 if isinstance(term, Variable) and self._need_ext_source_access(term, rel): |
565 if isinstance(term, Variable) \ |
|
566 and self._need_ext_source_access(term, rel): |
567 self.needsplit = True |
567 self.needsplit = True |
568 return |
568 return |
569 |
569 |
570 @cached |
570 @cached |
571 def _need_ext_source_access(self, var, rel): |
571 def _need_ext_source_access(self, var, rel): |