[Zope-CVS] CVS: Packages/pypes/pypes - interfaces.py:1.23 query.py:1.15

Casey Duncan casey at zope.com
Fri May 14 00:39:03 EDT 2004


Update of /cvs-repository/Packages/pypes/pypes
In directory cvs.zope.org:/tmp/cvs-serv23901

Modified Files:
	interfaces.py query.py 
Log Message:
Implement basic union & intersection for Join partial results
Implement actualized results
reload(sys)


=== Packages/pypes/pypes/interfaces.py 1.22 => 1.23 ===
--- Packages/pypes/pypes/interfaces.py:1.22	Tue May 11 23:48:47 2004
+++ Packages/pypes/pypes/interfaces.py	Fri May 14 00:38:29 2004
@@ -716,13 +716,13 @@
         PypesQueryError.
         """
         
-    def magnitude(*names):
-        """Return an integer which is the approximate length of the result
-        with the names specified. If no names are specified then the magnitude
-        for iterating all inputs is returned. Implementations should strive for
-        efficiency over accuracy, although accuracy can help the query engine 
-        determine a more efficient plan.
-        """
+    #def magnitude(*names):
+    #    """Return an integer which is the approximate length of the result
+    #    with the names specified. If no names are specified then the magnitude
+    #    for iterating all inputs is returned. Implementations should strive for
+    #    efficiency over accuracy, although accuracy can help the query engine 
+    #    determine a more efficient plan.
+    #    """
     
     def iterResult(*names):
         """Yield the items for the specified input names where the criteria
@@ -731,10 +731,10 @@
         matching items from the cooresponding named inputs.
         """
         
-    def resultSet(*names):
-        """Return an ISet object containing the items from the inputs named.
-        If a single name is specified, then return a set of matching objects
-        from the input. If multiple names are specified, return a set of
-        tuples of the matching items from the cooresponding named inputs.
-        """
+    #def resultSet(*names):
+    #    """Return an ISet object containing the items from the inputs named.
+    #    If a single name is specified, then return a set of matching objects
+    #    from the input. If multiple names are specified, return a set of
+    #   tuples of the matching items from the cooresponding named inputs.
+    #    """
 


=== Packages/pypes/pypes/query.py 1.14 => 1.15 ===
--- Packages/pypes/pypes/query.py:1.14	Thu May 13 00:33:37 2004
+++ Packages/pypes/pypes/query.py	Fri May 14 00:38:29 2004
@@ -47,7 +47,7 @@
 
 from operator import mul
 from sets import Set
-from itertools import imap
+from itertools import imap, ifilter
 from zope.interface import implements
 from compiler import ast
 from BTrees.OOBTree import OOBTree, OOTreeSet
@@ -330,7 +330,7 @@
         'in': injoin}
     
     def __init__(self, input_map, criteria):
-        """Construct the joins
+        """Construct the join
         
         input_map -- a mapping object mapping names => inputs.
         
@@ -387,6 +387,16 @@
     def namesUsed(self):
         return self._criteria.freeNames(self._inputs.keys())
         
+    def union(self, other):
+        inputs = union_input_maps(self.inputMap(), other.inputMap())
+        criteria = self.criteriaExpr() | other.criteriaExpr()
+        return CartProduct(inputs, criteria)
+    
+    def intersection(self, other):
+        inputs = intersect_input_maps(self.inputMap(), other.inputMap())
+        criteria = self.criteriaExpr() & other.criteriaExpr()
+        return CartProduct(inputs, criteria)
+        
     def _iterJoin(self, reverse=False):
         # Generates (left, right) pairs of joined terms
         join = self._join_ops[self._operator]
@@ -427,6 +437,108 @@
             return imap(output, self._iterJoin(self.reverse))
         else:
             raise NotImplementedError
+
+
+class ActualizedResult:
+    """Partial result with greedy evaluation.
+    
+    When instantiated, the inputs are processed immediately against the
+    criteria. The criteria may consist of one or more terms each filtering
+    exactly one input. Multiple terms are contained in a single AND
+    boolean operation.
+    """
+    
+    implements(IPartialResult)
+    
+    def __init__(self, input_map, criteria=None):
+        """Construct the actualized result
+        
+        input_map -- a mapping object mapping names => inputs.
+        
+        criteria -- criteria expression, an IExpression object. Supported
+        criteria consists of one or more terms that each refer to a single
+        input. If criteria is omitted, then the actualized result is the
+        same as the inputs provided.
+        
+        If the criteria is not supported, raise CantProcess
+        """
+        self._criteria = criteria
+        if criteria is not None:
+            node = criteria.ast().getChildNodes()[0]
+            if (len(criteria.freeNames(input_map.keys())) > 1 
+                and isinstance(node, ast.And)):
+                terms = node.getChildNodes()
+            else:
+                terms = (node,)
+            bindings = criteria.bindings()
+            filters = {} # Map input name => filter expression
+            for term in terms:
+                term_expr = Expression.fromAstNode(term, bindings)
+                try:
+                    input_name, = term_expr.freeNames()
+                except ValueError:
+                    raise CantProcess, \
+                        'cannot actualize result for criteria containing join'
+                if input_name not in input_map:
+                    raise PypesQueryInputError, \
+                        'name %s in criteria not found in inputs'
+                if input_name in filters:
+                    filters[input_name] = filters[input_name] & term_expr
+                else:
+                    filters[input_name] = term_expr
+
+            # Filter the inputs as results
+            self._inputs = {}
+            for name, ipt in input_map.items():
+                if name in filters:
+                    self._inputs[name] = Set(
+                        ifilter(filters[name].makeFunction(name), ipt))
+                else:
+                    self._inputs[name] = ipt
+        else:
+            self._inputs = input_map.copy()
+    
+    def inputMap(self):
+        return self._inputs.copy()
+        
+    def criteriaExpr(self):
+        return self._criteria
+    
+    def namesUsed(self):
+        return self._criteria.freeNames(self._inputs.keys())
+        
+    def union(self, other):
+        """A union with an actualized result returns a new partial result
+        the same class as other, with inputs unioned with self
+        """
+        if isinstance(other, ActualizedResult):
+            # Actualized results have already realized the criteria,
+            # Drop the criteria here to avoid redundant processing
+            criteria = None
+        else:
+            criteria = other.criteriaExpr()
+        inputs = union_input_maps(self.inputMap(), other.inputMap())
+        return other.__class__(inputs, criteria)
+    
+    def intersection(self, other):
+        """An intersection with an actualized result returns a new partial 
+        result the same class as other, with inputs intersected with self
+        """
+        if isinstance(other, ActualizedResult):
+            # Actualized results have already realized the criteria,
+            # Drop the criteria here to avoid redundant processing
+            criteria = None
+        else:
+            criteria = other.criteriaExpr()
+        inputs = intersect_input_maps(self.inputMap(), other.inputMap())
+        return other.__class__(inputs, criteria)
+    
+    def iterResult(self, *names):
+        if len(names) == 1:
+            return iter(self._inputs[names[0]])
+        else:
+            return CartProduct(self._inputs).iterResult(*names)
+
 
 def sort(iterable, expression, order=ascending, limit=None):
     """Return a sequence containing the elements of iterable sorted in order




More information about the Zope-CVS mailing list