server/msplanner.py
changeset 341 0a426be2f3a2
parent 257 4c7d3af7e94d
child 392 bccd9a788f7a
equal deleted inserted replaced
340:bfe0e95571aa 341:0a426be2f3a2
   178         # final relation which is supported by multiple sources
   178         # final relation which is supported by multiple sources
   179         self._linkedvars = {}
   179         self._linkedvars = {}
   180         # processing
   180         # processing
   181         self._compute_sourcesvars()
   181         self._compute_sourcesvars()
   182         self._remove_invalid_sources()
   182         self._remove_invalid_sources()
   183         #if server.DEBUG:
       
   184         #    print 'planner sources vars', self._sourcesvars
       
   185         self._compute_needsplit()
   183         self._compute_needsplit()
   186         self._inputmaps = {}
   184         self._inputmaps = {}
   187         if rqlhelper is not None: # else test
   185         if rqlhelper is not None: # else test
   188             self._insert_identity_variable = rqlhelper._annotator.rewrite_shared_optional
   186             self._insert_identity_variable = rqlhelper._annotator.rewrite_shared_optional
   189 
   187 
   210         """
   208         """
   211         return frozenset((source, solidx) for source in self._session.repo.sources
   209         return frozenset((source, solidx) for source in self._session.repo.sources
   212                          for solidx in self._solindices
   210                          for solidx in self._solindices
   213                          if not (source.support_relation(rtype)
   211                          if not (source.support_relation(rtype)
   214                                  or rtype in source.dont_cross_relations))
   212                                  or rtype in source.dont_cross_relations))
       
   213         
   215     
   214     
   216     def _compute_sourcesvars(self):
   215     def _compute_sourcesvars(self):
   217         """compute for each variable/solution in the rqlst which sources support
   216         """compute for each variable/solution in the rqlst which sources support
   218         them
   217         them
   219         """
   218         """
   275             # process non final relations only
   274             # process non final relations only
   276             # note: don't try to get schema for 'is' relation (not available
   275             # note: don't try to get schema for 'is' relation (not available
   277             # during bootstrap)
   276             # during bootstrap)
   278             if not rel.is_types_restriction() and not rschema(rel.r_type).is_final():
   277             if not rel.is_types_restriction() and not rschema(rel.r_type).is_final():
   279                 # nothing to do if relation is not supported by multiple sources
   278                 # nothing to do if relation is not supported by multiple sources
   280                 relsources = [source for source in repo.sources
   279                 relsources = repo.rel_type_sources(rel.r_type)
   281                               if source.support_relation(rel.r_type)
       
   282                               or rel.r_type in source.dont_cross_relations]
       
   283                 if len(relsources) < 2:
   280                 if len(relsources) < 2:
   284                     if relsources:# and not relsources[0] in self._sourcesvars:
   281                     if relsources:
   285                         # this means the relation is using a variable inlined as
   282                         # this means the relation is using a variable inlined as
   286                         # a constant and another unsupported variable, in which
   283                         # a constant and another unsupported variable, in which
   287                         # case we put the relation in sourcesvars
   284                         # case we put the relation in sourcesvars
   288                         self._sourcesvars.setdefault(relsources[0], {})[rel] = set(self._solindices)
   285                         self._sourcesvars.setdefault(relsources[0], {})[rel] = set(self._solindices)
   289                     continue
   286                     continue
   342                 elif source in self._sourcesvars:
   339                 elif source in self._sourcesvars:
   343                     source_scopes = frozenset(v.scope for v in self._sourcesvars[source])
   340                     source_scopes = frozenset(v.scope for v in self._sourcesvars[source])
   344                     for const in vconsts:
   341                     for const in vconsts:
   345                         if const.scope in source_scopes:
   342                         if const.scope in source_scopes:
   346                             self._set_source_for_var(source, const)
   343                             self._set_source_for_var(source, const)
   347         
   344                             
   348     def _extern_term(self, term, vsources, inserted):
   345     def _extern_term(self, term, vsources, inserted):
   349         var = term.variable
   346         var = term.variable
   350         if var.stinfo['constnode']:
   347         if var.stinfo['constnode']:
   351             termv = var.stinfo['constnode']
   348             termv = var.stinfo['constnode']
   352             vsources[termv] = self._term_sources(termv)
   349             vsources[termv] = self._term_sources(termv)
   359             if not termv in vsources:
   356             if not termv in vsources:
   360                 vsources[termv] = self._term_sources(termv)
   357                 vsources[termv] = self._term_sources(termv)
   361         return termv
   358         return termv
   362         
   359         
   363     def _remove_sources_until_stable(self, var, vsources):
   360     def _remove_sources_until_stable(self, var, vsources):
       
   361         sourcesvars = self._sourcesvars
   364         for ovar, rel in self._linkedvars.get(var, ()):
   362         for ovar, rel in self._linkedvars.get(var, ()):
   365             if not var.scope is ovar.scope and rel.scope.neged(strict=True):
   363             if not var.scope is ovar.scope and rel.scope.neged(strict=True):
   366                 # can't get information from relation inside a NOT exists
   364                 # can't get information from relation inside a NOT exists
   367                 # where variables don't belong to the same scope
   365                 # where variables don't belong to the same scope
   368                 continue
   366                 continue
   369             if rel.neged(strict=True):
   367             relsources = self._session.repo.rel_type_sources(rel.r_type)
   370                 # neged relation doesn't allow to infer variable sources
   368             if rel.neged(strict=True) and (
       
   369                 len(relsources) < 2
       
   370                 or not isinstance(ovar, Variable)
       
   371                 or ovar.valuable_references() != 1
       
   372                 or any(sourcesvars[source][var] != sourcesvars[source][ovar]
       
   373                        for source in relsources
       
   374                        if var in sourcesvars.get(source, ())
       
   375                        and ovar in sourcesvars.get(source, ()))):
       
   376                 # neged relation doesn't allow to infer variable sources unless we're
       
   377                 # on a multisource relation for a variable only used by this relation
       
   378                 # (eg "Any X WHERE NOT X multisource_rel Y" and over is Y), iif 
   371                 continue
   379                 continue
   372             norelsup = self._norel_support_set(rel.r_type)
   380             norelsup = self._norel_support_set(rel.r_type)
   373             # compute invalid sources for variables and remove them
   381             # compute invalid sources for variables and remove them
   374             self._remove_var_sources(var, norelsup, ovar, vsources)
   382             self._remove_var_sources(var, norelsup, ovar, vsources)
   375             self._remove_var_sources(ovar, norelsup, var, vsources)
   383             self._remove_var_sources(ovar, norelsup, var, vsources)
   896         # finally: join parts, deal with aggregat/group/sorts if necessary
   904         # finally: join parts, deal with aggregat/group/sorts if necessary
   897         if atemptable is not None:
   905         if atemptable is not None:
   898             step = AggrStep(plan, selection, select, atemptable, temptable)
   906             step = AggrStep(plan, selection, select, atemptable, temptable)
   899             step.children = steps
   907             step.children = steps
   900         elif len(steps) > 1:
   908         elif len(steps) > 1:
   901             if temptable:
   909             if select.need_intersect:
   902                 step = UnionFetchStep(plan)
   910                 if temptable:
       
   911                     step = IntersectFetchStep(plan)
       
   912                 else:
       
   913                     step = IntersectStep(plan)
   903             else:
   914             else:
   904                 step = UnionStep(plan)
   915                 if temptable:
       
   916                     step = UnionFetchStep(plan)
       
   917                 else:
       
   918                     step = UnionStep(plan)
   905             step.children = steps
   919             step.children = steps
   906         else:
   920         else:
   907             step = steps[0]
   921             step = steps[0]
   908         if select.limit is not None or select.offset:
   922         if select.limit is not None or select.offset:
   909             step.set_limit_offset(select.limit, select.offset)
   923             step.set_limit_offset(select.limit, select.offset)