server/msplanner.py
changeset 341 0a426be2f3a2
parent 257 4c7d3af7e94d
child 392 bccd9a788f7a
--- a/server/msplanner.py	Wed Jan 07 14:55:16 2009 +0100
+++ b/server/msplanner.py	Wed Jan 07 14:57:03 2009 +0100
@@ -180,8 +180,6 @@
         # processing
         self._compute_sourcesvars()
         self._remove_invalid_sources()
-        #if server.DEBUG:
-        #    print 'planner sources vars', self._sourcesvars
         self._compute_needsplit()
         self._inputmaps = {}
         if rqlhelper is not None: # else test
@@ -212,6 +210,7 @@
                          for solidx in self._solindices
                          if not (source.support_relation(rtype)
                                  or rtype in source.dont_cross_relations))
+        
     
     def _compute_sourcesvars(self):
         """compute for each variable/solution in the rqlst which sources support
@@ -277,11 +276,9 @@
             # during bootstrap)
             if not rel.is_types_restriction() and not rschema(rel.r_type).is_final():
                 # nothing to do if relation is not supported by multiple sources
-                relsources = [source for source in repo.sources
-                              if source.support_relation(rel.r_type)
-                              or rel.r_type in source.dont_cross_relations]
+                relsources = repo.rel_type_sources(rel.r_type)
                 if len(relsources) < 2:
-                    if relsources:# and not relsources[0] in self._sourcesvars:
+                    if relsources:
                         # this means the relation is using a variable inlined as
                         # a constant and another unsupported variable, in which
                         # case we put the relation in sourcesvars
@@ -344,7 +341,7 @@
                     for const in vconsts:
                         if const.scope in source_scopes:
                             self._set_source_for_var(source, const)
-        
+                            
     def _extern_term(self, term, vsources, inserted):
         var = term.variable
         if var.stinfo['constnode']:
@@ -361,13 +358,24 @@
         return termv
         
     def _remove_sources_until_stable(self, var, vsources):
+        sourcesvars = self._sourcesvars
         for ovar, rel in self._linkedvars.get(var, ()):
             if not var.scope is ovar.scope and rel.scope.neged(strict=True):
                 # can't get information from relation inside a NOT exists
                 # where variables don't belong to the same scope
                 continue
-            if rel.neged(strict=True):
-                # neged relation doesn't allow to infer variable sources
+            relsources = self._session.repo.rel_type_sources(rel.r_type)
+            if rel.neged(strict=True) and (
+                len(relsources) < 2
+                or not isinstance(ovar, Variable)
+                or ovar.valuable_references() != 1
+                or any(sourcesvars[source][var] != sourcesvars[source][ovar]
+                       for source in relsources
+                       if var in sourcesvars.get(source, ())
+                       and ovar in sourcesvars.get(source, ()))):
+                # neged relation doesn't allow to infer variable sources unless we're
+                # on a multisource relation for a variable only used by this relation
+                # (eg "Any X WHERE NOT X multisource_rel Y" and over is Y), iif 
                 continue
             norelsup = self._norel_support_set(rel.r_type)
             # compute invalid sources for variables and remove them
@@ -898,10 +906,16 @@
             step = AggrStep(plan, selection, select, atemptable, temptable)
             step.children = steps
         elif len(steps) > 1:
-            if temptable:
-                step = UnionFetchStep(plan)
+            if select.need_intersect:
+                if temptable:
+                    step = IntersectFetchStep(plan)
+                else:
+                    step = IntersectStep(plan)
             else:
-                step = UnionStep(plan)
+                if temptable:
+                    step = UnionFetchStep(plan)
+                else:
+                    step = UnionStep(plan)
             step.children = steps
         else:
             step = steps[0]