[Checkins] SVN: Sandbox/adamg/ocql/trunk/src/ocql/ merge of branch optimize-with-index

Adam Groszer agroszer at gmail.com
Fri Aug 8 05:13:05 EDT 2008


Log message for revision 89534:
  merge of branch optimize-with-index

Changed:
  U   Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/aoptimizer.py
  U   Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/aoptimizer.txt
  A   Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/aoptimizer_new.txt
  U   Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/tests.py
  U   Sandbox/adamg/ocql/trunk/src/ocql/compiler/compiler.py
  U   Sandbox/adamg/ocql/trunk/src/ocql/compiler/compiler.txt
  A   Sandbox/adamg/ocql/trunk/src/ocql/compiler/optimize_index.txt
  U   Sandbox/adamg/ocql/trunk/src/ocql/compiler/runnablequery.py
  U   Sandbox/adamg/ocql/trunk/src/ocql/compiler/tests.py
  U   Sandbox/adamg/ocql/trunk/src/ocql/database/metadata.py
  U   Sandbox/adamg/ocql/trunk/src/ocql/engine.py
  D   Sandbox/adamg/ocql/trunk/src/ocql/parser/queryparser.py
  A   Sandbox/adamg/ocql/trunk/src/ocql/parser/queryparser.py
  U   Sandbox/adamg/ocql/trunk/src/ocql/rewriter/algebra.py
  U   Sandbox/adamg/ocql/trunk/src/ocql/rewriter/interfaces.py
  U   Sandbox/adamg/ocql/trunk/src/ocql/rewriter/rewriter.txt
  U   Sandbox/adamg/ocql/trunk/src/ocql/testing/database.py
  U   Sandbox/adamg/ocql/trunk/src/ocql/testing/sample/interfaces.py
  U   Sandbox/adamg/ocql/trunk/src/ocql/testing/sample/project.py
  U   Sandbox/adamg/ocql/trunk/src/ocql/testing/sample/student.py
  U   Sandbox/adamg/ocql/trunk/src/ocql/testing/stubs.py
  U   Sandbox/adamg/ocql/trunk/src/ocql/testing/utils.py
  A   Sandbox/adamg/ocql/trunk/src/ocql/testing/utils_opt.py
  U   Sandbox/adamg/ocql/trunk/src/ocql/tests/run.txt
  U   Sandbox/adamg/ocql/trunk/src/ocql/tests/test_old.py
  U   Sandbox/adamg/ocql/trunk/src/ocql/tests/test_zope.py

-=-
Modified: Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/aoptimizer.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/aoptimizer.py	2008-08-08 09:04:59 UTC (rev 89533)
+++ Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/aoptimizer.py	2008-08-08 09:13:02 UTC (rev 89534)
@@ -5,9 +5,10 @@
 
 $Id$
 """
-
+from collections import deque
 from zope.component import adapts
 from zope.interface import implements
+from zope.location import locate
 #from zope.security.proxy import removeSecurityProxy
 from zope.interface import directlyProvidedBy
 from zope.interface import directlyProvides
@@ -16,7 +17,74 @@
 
 from ocql.interfaces import IAlgebraObjectHead
 from ocql.interfaces import IOptimizedAlgebraObject
+from ocql.rewriter.algebra import *
 
+def bfsFind(tree):
+    """Breadth-first search to find a Iter Algebra object."""
+    visited = set()
+    queue = [tree]
+    while len(queue):
+        curr_node = queue.pop(0)
+        if isinstance(curr_node, Iter):
+            return curr_node
+        if isinstance(curr_node, BaseAlgebra):
+            visited.add(curr_node)
+            queue.extend(c for c in curr_node.children
+                         if c not in visited and c not in queue)
+
+
+def findItrTreePattern(tree):
+    """Checks whole Iter tree pattern exists stating from the Iter algebra object"""
+    iter_obj = bfsFind(tree)
+    if iter_obj is not None:
+        #need to check If and Make objects present
+        if (isinstance(iter_obj.func, Lambda) and isinstance(iter_obj.coll, Make)):
+            if isinstance(iter_obj.func.expr, If):
+                if isinstance(iter_obj.func.expr.cond , Binary):
+                    return iter_obj
+    return None
+
+
+def iterPatternMatcher(metadata, tree):
+    """Replaces the identified Iter tree pattern """
+    coll = tree.klass
+    single = tree.func.expr.expr1
+    var = tree.func.var
+    interface = tree.coll.expr.name
+    cond = tree.func.expr.cond.left.name
+    operator = tree.func.expr.cond.op.op
+    if isinstance(tree.func.expr.cond.right, Constant):
+        value = tree.func.expr.cond.right.value
+    elif isinstance(tree.func.expr.cond.right, Identifier):
+        value = tree.func.expr.cond.right.name
+    else:
+        return tree.__parent__
+
+    if not metadata.hasPropertyIndex(interface, cond.split(".")[1]):
+        return tree.__parent__
+
+    #new algebra objects
+    if operator:
+        makeFromIndex = MakeFromIndex(coll , coll, interface,
+                                      cond.split(".")[1],
+                                      operator, value=value)
+    else:
+        return tree.__parent__
+
+    newlambda = Lambda(var, single)
+    newTree = Iter(coll, newlambda, makeFromIndex)
+    parent = tree.__parent__
+    if isinstance(parent, Head):
+        return Head(newTree)
+    else:
+        for c in parent.children:
+            if isinstance(c, Iter):
+                del c
+        parent.children.append(newTree)
+        locate(newTree, parent, 'iter')
+        return newTree
+
+
 def addMarkerIF(obj, marker):
     #obj = removeSecurityProxy(obj)
     if not marker.providedBy(obj):
@@ -30,6 +98,13 @@
         self.context = context
         #self.db = db
 
-    def __call__(self):
+    def __call__(self, metadata):
+        results = findItrTreePattern(self.context.tree)
+
+        if results is not None:
+            alg = iterPatternMatcher(metadata, results)
+            addMarkerIF(alg, IOptimizedAlgebraObject)
+            return alg
+
         addMarkerIF(self.context, IOptimizedAlgebraObject)
         return self.context

Modified: Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/aoptimizer.txt
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/aoptimizer.txt	2008-08-08 09:04:59 UTC (rev 89533)
+++ Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/aoptimizer.txt	2008-08-08 09:13:02 UTC (rev 89534)
@@ -1,24 +1,31 @@
 
+    >>> from zope.interface.verify import verifyObject
 
+    >>> from ocql.interfaces import IAlgebraOptimizer
     >>> from ocql.aoptimizer.aoptimizer import AlgebraOptimizer
     >>> from ocql.interfaces import IOptimizedAlgebraObject
+    >>> from ocql.interfaces import IDB
 
-Currently the optimizer is doing NOTHING, it just returns what it gets.
-(And adds the interface IOptimizedAlgebraObject)
+#Currently the optimizer is doing NOTHING, it just returns what it gets.
+#(And adds the interface IOptimizedAlgebraObject)
 
     >>> class Dummy(object):
-    ...     def __init__(self, value):
-    ...          self.value = value
+    ...     def __init__(self, tree):
+    ...          self.tree = tree
 
     >>> in_=Dummy('foo-bar')
-    >>> in_.value
+    >>> in_.tree
     'foo-bar'
 
-    >>> out = AlgebraOptimizer(in_)()
+    >>> obj = AlgebraOptimizer(in_)
+    >>> verifyObject(IAlgebraOptimizer, obj)
+    True
 
+    >>> out = obj(None)
+
     >>> print out
     <Dummy object at ...>
-    >>> out.value
+    >>> out.tree
     'foo-bar'
 
     >>> IOptimizedAlgebraObject.providedBy(out)

Copied: Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/aoptimizer_new.txt (from rev 89533, Sandbox/adamg/ocql/branches/optimize-with-index/src/ocql/aoptimizer/aoptimizer_new.txt)
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/aoptimizer_new.txt	                        (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/aoptimizer_new.txt	2008-08-08 09:13:02 UTC (rev 89534)
@@ -0,0 +1,59 @@
+
+Queries in the rewriter.txt are extended to AlgebraOptimization
+
+    >>> from ocql.aoptimizer.aoptimizer import AlgebraOptimizer
+    >>> from ocql.interfaces import IOptimizedAlgebraObject
+    >>> from ocql.parser.queryparser import QueryParser
+    >>> from ocql.qoptimizer.qoptimizer import QueryOptimizer
+    >>> from ocql.rewriter.rewriter import Rewriter
+
+    >>> from ocql.testing.database import TestMetadata
+
+    >>> import ocql.compiler.compiler
+    >>> ocql.compiler.compiler.registerAdapters()
+
+    >>> import ocql.rewriter.rewriter
+    >>> ocql.rewriter.rewriter.registerAdapters()
+
+
+    >>> qo = QueryParser("set [ | 1 ]")(TestMetadata())
+    >>> opt = QueryOptimizer(qo)()
+    >>> alg = Rewriter(opt)()
+    >>> out = AlgebraOptimizer(alg)(TestMetadata())
+    >>> print str(out)
+    Single(<type 'set'>, `1`)
+
+    >>> qo = QueryParser("set [ | 1 ] union set [|2]")(TestMetadata())
+    >>> opt = QueryOptimizer(qo)()
+    >>> alg = Rewriter(opt)()
+    >>> out = AlgebraOptimizer(alg)(TestMetadata())
+    >>> print str(out)
+    Union(<type 'set'>, Single(<type 'set'>, `1`), Single(<type 'set'>, `2`))
+
+    #Differ not implemented
+    #>>> qo = QueryParser("set [ | 1 ] differ set [|2]")(TestMetadata())
+    #>>> opt = QueryOptimizer(qo)()
+    #>>> alg = Rewriter(opt)()
+    #>>> print str(alg)
+    #Union(<type 'set'>, Single(<type 'set'>, `1`), Single(<type 'set'>, `2`))
+
+    >>> qo = QueryParser("set [ i in ICourse | i ]")(TestMetadata())
+    >>> opt = QueryOptimizer(qo)()
+    >>> alg = Rewriter(opt)()
+    >>> out = AlgebraOptimizer(alg)(TestMetadata())
+    >>> print str(out)
+    Iter(<type 'set'>, Lambda i: Single(<type 'set'>, i), Make(<type 'set'>, <type 'set'>, ICourse))
+
+    #>>> qo = QueryParser("set [ c in ICourse; c.credits>3 | c.code ]")(TestMetadata())
+    #>>> opt = QueryOptimizer(qo)()
+    #>>> alg = Rewriter(opt)()
+    #>>> out = AlgebraOptimizer(alg)(TestMetadata())
+    #>>> print str(out)
+    #Iter(<type 'set'>, Lambda c: If(c.credits>`3`, Single(<type 'set'>, c.code), Empty(<type 'set'>)), Make(<type 'set'>, <type 'set'>, ICourse))
+
+    #bag not implemented
+    #>>> qo = QueryParser("size set [ i in ICourse | i ]")(TestMetadata())
+    #>>> opt = QueryOptimizer(qo)()
+    #>>> alg = Rewriter(opt)()
+    #>>> print str(alg)
+    #Iter(<type 'set'>, Lambda i: Single(<type 'set'>, i), Make(<type 'set'>, <type 'set'>, ICourse))
\ No newline at end of file

Modified: Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/tests.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/tests.py	2008-08-08 09:04:59 UTC (rev 89533)
+++ Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/tests.py	2008-08-08 09:13:02 UTC (rev 89534)
@@ -5,8 +5,12 @@
 def test_suite():
     flags =  doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS
     return unittest.TestSuite((
+# avoid this tests for convenient while adding new implementation to the algebra optimizer
+#need to add aoptimizer.txt
         DocFileSuite('aoptimizer.txt',
             optionflags=flags),
+        DocFileSuite('aoptimizer_new.txt',
+            optionflags=flags),
         ))
 
 

Modified: Sandbox/adamg/ocql/trunk/src/ocql/compiler/compiler.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/compiler/compiler.py	2008-08-08 09:04:59 UTC (rev 89533)
+++ Sandbox/adamg/ocql/trunk/src/ocql/compiler/compiler.py	2008-08-08 09:13:02 UTC (rev 89534)
@@ -102,7 +102,7 @@
         self.context.expr is IfCompiler:
 
             if self.context.klass == set:
-                return 'reduce(set.union, map(%s,%s), set())' % (
+                return 'reduce(set.union, map(%s, %s), set())' % (
                     IAlgebraCompiler(self.context.func)(),
                     IAlgebraCompiler(self.context.coll)())
             if self.context.klass == list:
@@ -111,7 +111,7 @@
                     IAlgebraCompiler(self.context.coll)())
         else:
             if self.context.klass == set:
-                return 'reduce(set.union, map(%s,%s), set())' % (
+                return 'reduce(set.union, map(%s, %s), set())' % (
                     IAlgebraCompiler(self.context.func)(),
                     IAlgebraCompiler(self.context.coll)())
             if self.context.klass == list:
@@ -179,6 +179,19 @@
             IAlgebraCompiler(self.context.expr)())
 
 
+class MakeFromIndexCompiler(BaseCompiler):
+    implements(IAlgebraCompiler)
+    adapts(IMakeFromIndex)
+
+    def __call__(self):
+        return '%s(metadata.getFromIndex("%s", "%s", "%s", %s))' % (
+            self.context.coll1.__name__,
+            self.context.expr1,
+            self.context.expr2,
+            self.context.operator,
+            self.context.value)
+
+
 class IfCompiler(BaseCompiler):
     implements(IAlgebraCompiler)
     adapts(IIf)
@@ -256,6 +269,7 @@
     provideAdapter(ReduceCompiler)
     provideAdapter(RangeCompiler)
     provideAdapter(MakeCompiler)
+    provideAdapter(MakeFromIndexCompiler)
     provideAdapter(IfCompiler)
     provideAdapter(LambdaCompiler)
     provideAdapter(ConstantCompiler)

Modified: Sandbox/adamg/ocql/trunk/src/ocql/compiler/compiler.txt
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/compiler/compiler.txt	2008-08-08 09:04:59 UTC (rev 89533)
+++ Sandbox/adamg/ocql/trunk/src/ocql/compiler/compiler.txt	2008-08-08 09:13:02 UTC (rev 89534)
@@ -21,7 +21,7 @@
     >>> qo = QueryParser("set [ | 1 ]")(metadata)
     >>> opt = QueryOptimizer(qo)()
     >>> alg = Rewriter(opt)()
-    >>> aopt = AlgebraOptimizer(alg)()
+    >>> aopt = AlgebraOptimizer(alg)(metadata)
     >>> run = AlgebraCompiler(aopt)(metadata, alg)
     >>> print str(run)
     RunnableQuery: set([1])
@@ -30,7 +30,7 @@
     >>> qo = QueryParser("list [ | 1 ]")(metadata)
     >>> opt = QueryOptimizer(qo)()
     >>> alg = Rewriter(opt)()
-    >>> aopt = AlgebraOptimizer(alg)()
+    >>> aopt = AlgebraOptimizer(alg)(metadata)
     >>> run = AlgebraCompiler(aopt)(metadata, alg)
     >>> print str(run)
     RunnableQuery: [1]
@@ -39,7 +39,7 @@
     >>> qo = QueryParser("set [ | 1 ] union set [|2]")(TestMetadata())
     >>> opt = QueryOptimizer(qo)()
     >>> alg = Rewriter(opt)()
-    >>> aopt = AlgebraOptimizer(alg)()
+    >>> aopt = AlgebraOptimizer(alg)(metadata)
     >>> run = AlgebraCompiler(aopt)(metadata, alg)
     >>> print str(run)
     RunnableQuery: set.union(set([1]), set([2]))
@@ -48,7 +48,7 @@
     >>> qo = QueryParser("list [ | 1 ] union list [|2]")(TestMetadata())
     >>> opt = QueryOptimizer(qo)()
     >>> alg = Rewriter(opt)()
-    >>> aopt = AlgebraOptimizer(alg)()
+    >>> aopt = AlgebraOptimizer(alg)(metadata)
     >>> run = AlgebraCompiler(aopt)(metadata, alg)
     >>> print str(run)
     RunnableQuery: ([1])+([2])
@@ -56,7 +56,7 @@
     >>> qo = QueryParser("set [ | 1 ] differ set [|2]")(TestMetadata())
     >>> opt = QueryOptimizer(qo)()
     >>> alg = Rewriter(opt)()
-    >>> aopt = AlgebraOptimizer(alg)()
+    >>> aopt = AlgebraOptimizer(alg)(metadata)
     >>> run = AlgebraCompiler(aopt)(metadata, alg)
     >>> print str(run)
     RunnableQuery: set.differ(set([1]), set([2]))
@@ -64,7 +64,7 @@
     >>> qo = QueryParser("list [ | 1 ] differ list [|2]")(TestMetadata())
     >>> opt = QueryOptimizer(qo)()
     >>> alg = Rewriter(opt)()
-    >>> aopt = AlgebraOptimizer(alg)()
+    >>> aopt = AlgebraOptimizer(alg)(metadata)
     >>> run = AlgebraCompiler(aopt)(metadata, alg)
     >>> print str(run)
     RunnableQuery: ([1])-([2])
@@ -73,16 +73,16 @@
     >>> qo = QueryParser("set [ i in ICourse | i ]")(TestMetadata())
     >>> opt = QueryOptimizer(qo)()
     >>> alg = Rewriter(opt)()
-    >>> aopt = AlgebraOptimizer(alg)()
+    >>> aopt = AlgebraOptimizer(alg)(metadata)
     >>> run = AlgebraCompiler(aopt)(metadata, alg)
     >>> print str(run)
-    RunnableQuery: reduce(set.union, map(lambda i: set([i]),set(metadata.getAll("ICourse"))), set())
+    RunnableQuery: reduce(set.union, map(lambda i: set([i]), set(metadata.getAll("ICourse"))), set())
 
     >>> metadata = TestMetadata()
     >>> qo = QueryParser("list [ i in ICourse | i ]")(TestMetadata())
     >>> opt = QueryOptimizer(qo)()
     >>> alg = Rewriter(opt)()
-    >>> aopt = AlgebraOptimizer(alg)()
+    >>> aopt = AlgebraOptimizer(alg)(metadata)
     >>> run = AlgebraCompiler(aopt)(metadata, alg)
     >>> print str(run)
     RunnableQuery: reduce(operator.add, map(lambda i: [i], list(metadata.getAll("ICourse"))), [])
@@ -98,16 +98,16 @@
     >>> qo = QueryParser("set [ c in ICourse | c.code ]")(TestMetadata())
     >>> opt = QueryOptimizer(qo)()
     >>> alg = Rewriter(opt)()
-    >>> aopt = AlgebraOptimizer(alg)()
+    >>> aopt = AlgebraOptimizer(alg)(metadata)
     >>> run = AlgebraCompiler(aopt)(metadata, alg)
     >>> print str(run)
-    RunnableQuery: reduce(set.union, map(lambda c: set([c.code]),set(metadata.getAll("ICourse"))), set())
+    RunnableQuery: reduce(set.union, map(lambda c: set([c.code]), set(metadata.getAll("ICourse"))), set())
 
     >>> metadata = TestMetadata()
     >>> qo = QueryParser("list [ c in ICourse | c.code ]")(TestMetadata())
     >>> opt = QueryOptimizer(qo)()
     >>> alg = Rewriter(opt)()
-    >>> aopt = AlgebraOptimizer(alg)()
+    >>> aopt = AlgebraOptimizer(alg)(metadata)
     >>> run = AlgebraCompiler(aopt)(metadata, alg)
     >>> print str(run)
     RunnableQuery: reduce(operator.add, map(lambda c: [c.code], list(metadata.getAll("ICourse"))), [])

Copied: Sandbox/adamg/ocql/trunk/src/ocql/compiler/optimize_index.txt (from rev 89533, Sandbox/adamg/ocql/branches/optimize-with-index/src/ocql/compiler/optimize_index.txt)
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/compiler/optimize_index.txt	                        (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/compiler/optimize_index.txt	2008-08-08 09:13:02 UTC (rev 89534)
@@ -0,0 +1,153 @@
+
+Checking here how a compiled query can be optimized for zope indexes
+
+    >>> from zope.component import provideAdapter
+
+    >>> from ocql.parser.queryparser import QueryParser
+    >>> from ocql.qoptimizer.qoptimizer import QueryOptimizer
+    >>> from ocql.rewriter.rewriter import Rewriter
+    >>> from ocql.aoptimizer.aoptimizer import AlgebraOptimizer
+    >>> from ocql.compiler.compiler import AlgebraCompiler
+    >>> from ocql.database.metadata import Metadata
+
+    >>> provideAdapter(QueryParser)
+    >>> provideAdapter(QueryOptimizer)
+    >>> provideAdapter(Rewriter)
+    >>> provideAdapter(AlgebraOptimizer)
+    >>> provideAdapter(AlgebraCompiler)
+    >>> provideAdapter(Metadata)
+
+    >>> from ocql.engine import OCQLEngine
+
+    >>> import ocql.compiler.compiler
+    >>> ocql.compiler.compiler.registerAdapters()
+
+    >>> import ocql.rewriter.rewriter
+    >>> ocql.rewriter.rewriter.registerAdapters()
+
+    >>> from ocql.testing.utils_opt import setupInterfaces
+    >>> setupInterfaces(None)
+    >>> from ocql.testing.utils_opt import setupCatalog
+    >>> setupCatalog(None)
+
+
+Simple thing:
+
+    #>>> engine = OCQLEngine()
+    #>>> run = engine.compile("set [ | 1 ]")
+    #>>> run
+    #RunnableQuery: set([1])
+    #
+    #>>> result = run.execute()
+    #>>> result
+    #set([1])
+
+
+Let's use the IUnOptimizedClass:
+
+#    >>> engine = OCQLEngine()
+#    >>> run = engine.compile("set [ i in IUnOptimizedClass | i ]")
+#    >>> run
+#    RunnableQuery: reduce(set.union, map(lambda i: set([i]), set(metadata.getAll("IUnOptimizedClass"))), set())
+#
+##    >>> result = run.execute()
+##    >>> result
+##    set([UnOpt: 0, UnOpt: 1, UnOpt: 3, UnOpt: 4, UnOpt: 5, UnOpt: 6, UnOpt: 7, UnOpt: 2, UnOpt: 8, UnOpt: 9])
+
+
+IUnOptimizedClass with a filter condition:
+(parser is not working, therefore the complicated query definition)
+
+    >>> from ocql.queryobject.queryobject import *
+    >>> from ocql.interfaces import IDB
+    >>> from ocql.parser.queryparser import SymbolContainer
+
+    >>> metadata = IDB(None)
+    >>> symbols = SymbolContainer()
+    >>> qo = Head(Query(
+    ...         metadata, symbols,
+    ...         set,
+    ...         [
+    ...              In(
+    ...                 metadata, symbols,
+    ...                 Identifier(metadata,symbols,'i'),
+    ...                 Identifier(metadata,symbols, 'IUnOptimizedClass')),
+    ...              Eq(
+    ...                 metadata,symbols,
+    ...                 Identifier(metadata, symbols, 'i.value'),
+    ...                 Identifier(metadata, symbols, '5'))
+    ...         ], Identifier(metadata, symbols, 'i.name')))
+
+
+    >>> engine = OCQLEngine()
+    >>> run = engine.compile(qo)
+    >>> run
+    RunnableQuery:
+    reduce(set.union,
+    map(lambda i: ((i.value==5) and (set([i.name])) or (set())),
+    set(metadata.getAll("IUnOptimizedClass"))), set())
+
+Here is the algebra tree:
+
+    >>> run.alg
+    Iter(<type 'set'>,
+    Lambda i: If(i.value==5, Single(<type 'set'>, i.name), Empty(<type 'set'>)),
+    Make(<type 'set'>, <type 'set'>, IUnOptimizedClass))
+
+Results of the query:
+
+    >>> result = run.execute()
+    >>> result
+    set([u'5'])
+
+
+
+IOptimizedClass with a filter condition:
+(parser is not working, therefore the complicated query definition)
+
+    >>> from ocql.queryobject.queryobject import *
+    >>> from ocql.interfaces import IDB
+    >>> from ocql.parser.queryparser import SymbolContainer
+
+    >>> metadata = IDB(None)
+    >>> symbols = SymbolContainer()
+    >>> qo = Head(Query(
+    ...         metadata, symbols,
+    ...         set,
+    ...         [
+    ...              In(
+    ...                 metadata, symbols,
+    ...                 Identifier(metadata,symbols,'i'),
+    ...                 Identifier(metadata,symbols, 'IOptimizedClass')),
+    ...              Eq(
+    ...                 metadata,symbols,
+    ...                 Identifier(metadata, symbols, 'i.value'),
+    ...                 Identifier(metadata, symbols, '5'))
+    ...         ], Identifier(metadata, symbols, 'i.name')))
+
+
+    >>> engine = OCQLEngine()
+    >>> run = engine.compile(qo)
+    >>> run
+    RunnableQuery:
+    reduce(set.union,
+    map(lambda i: set([i.name]),
+    set(metadata.getFromIndex("IOptimizedClass", "value", "==", 5))), set())
+
+
+
+    >>> result = run.execute()
+    >>> result
+    set([u'5'])
+
+
+
+
+    #>>> engine = OCQLEngine()
+    #>>> run = engine.compile("set [ i in IUnOptimizedClass; i.value==5 | i.name ]")
+    #>>> run
+    #RunnableQuery: reduce(set.union, map(lambda i: set([i]),set(metadata.getAll("IUnOptimizedClass"))), set())
+
+#    >>> result = run.execute()
+#    >>> result
+#    set([UnOpt: 0, UnOpt: 1, UnOpt: 3, UnOpt: 4, UnOpt: 5, UnOpt: 6, UnOpt: 7, UnOpt: 2, UnOpt: 8, UnOpt: 9])

Modified: Sandbox/adamg/ocql/trunk/src/ocql/compiler/runnablequery.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/compiler/runnablequery.py	2008-08-08 09:04:59 UTC (rev 89533)
+++ Sandbox/adamg/ocql/trunk/src/ocql/compiler/runnablequery.py	2008-08-08 09:13:02 UTC (rev 89534)
@@ -60,8 +60,8 @@
                            self.code)
 
     def reanalyze(self):
-        optimizedalgebra = IAlgebraOptimizer(self.alg)()
-        runnable = IAlgebraCompiler(optimizedalgebra)(self.metadata, self.alg)
+        optimizedalgebra = IAlgebraOptimizer(self.alg)(self.metadata)
+        runnable = IAlgebraCompiler(optimizedalgebra)(self.metadata, optimizedalgebra)
         return runnable
 
     def execute(self, debug=False):

Modified: Sandbox/adamg/ocql/trunk/src/ocql/compiler/tests.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/compiler/tests.py	2008-08-08 09:04:59 UTC (rev 89533)
+++ Sandbox/adamg/ocql/trunk/src/ocql/compiler/tests.py	2008-08-08 09:13:02 UTC (rev 89534)
@@ -5,6 +5,8 @@
 def test_suite():
     flags =  doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS
     return unittest.TestSuite((
+        DocFileSuite('optimize_index.txt',
+            optionflags=flags),
         DocFileSuite('compiler.txt',
             optionflags=flags),
         ))

Modified: Sandbox/adamg/ocql/trunk/src/ocql/database/metadata.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/database/metadata.py	2008-08-08 09:04:59 UTC (rev 89533)
+++ Sandbox/adamg/ocql/trunk/src/ocql/database/metadata.py	2008-08-08 09:13:02 UTC (rev 89534)
@@ -5,8 +5,10 @@
 from zope.component import getUtility
 from zope.component import getUtilitiesFor
 from zope.app.catalog.interfaces import ICatalog
+from zope.app.catalog.field import FieldIndex
 from zope.app.intid import IIntIds
-import zc.relation.interfaces
+#import zc.relation.interfaces
+from BTrees.IFBTree import difference
 
 from ocql.interfaces import IDB
 from ocql.database.index import AllIndex
@@ -88,13 +90,56 @@
             for iname, index in catalog.items():
                 if isinstance(index, AllIndex):
                     if index.interface.__name__ == klassname:
-                        interface = index.interface
                         results = catalog.apply({iname:(1,1)})
                         obj_list = [intids.getObject(result) for result in results]
                         return obj_list
 
         return None
 
+    def getFromIndex(self, klass, property, operator, value):
+        catalogs = getUtilitiesFor(ICatalog)
+        intids = getUtility(IIntIds)
+        for name, catalog in catalogs:
+            for iname, index in catalog.items():
+                if isinstance(index, FieldIndex) and \
+                index.field_name == property and \
+                index.interface.__name__ == klass:
+                    if operator == '==':
+                        results = catalog.apply({iname:(value, value)})
+                    elif operator == '!=':
+                        all = catalog.apply({iname:(None, None)})
+                        temp = catalog.apply({iname:(value, value)})
+                        results = difference(all, temp)
+                    elif operator == '<=':
+                        results = catalog.apply({iname:(value, None)})
+                    elif operator == '<':
+                        lt_eq = catalog.apply({iname:(value, None)})
+                        temp = catalog.apply({iname:(value, value)})
+                        results = difference(lt_eq, temp)
+                    elif operator == '>=':
+                        results = catalog.apply({iname:(None, value)})
+                    elif operator == '>':
+                        gt_eq = catalog.apply({iname:(None, value)})
+                        temp = catalog.apply({iname:(value, value)})
+                        results = difference(gt_eq, temp)
+
+                    obj_list = [intids.getObject(result) for result in results]
+                    return obj_list
+        #I could check whether property has an index by hasPropertyIndex. 
+        #But by this approach this always returns IF objects
+        return self.getAll(klass)
+
+    def hasPropertyIndex(self, klass, property):
+        catalogs = getUtilitiesFor(ICatalog)
+        for name, catalog in catalogs:
+            for iname, index in catalog.items():
+                if isinstance(index, FieldIndex) and \
+                index.field_name == property and \
+                index.interface.__name__ == klass:
+                    return True
+        return False
+
+
     def get_class(self, klassname):
         """Returns a MetaType instance for the class."""
         return self.classes[klassname]

Modified: Sandbox/adamg/ocql/trunk/src/ocql/engine.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/engine.py	2008-08-08 09:04:59 UTC (rev 89533)
+++ Sandbox/adamg/ocql/trunk/src/ocql/engine.py	2008-08-08 09:13:02 UTC (rev 89534)
@@ -17,11 +17,11 @@
 from ocql.interfaces import IAlgebraCompiler
 from ocql.interfaces import IDB
 
-from ocql.interfaces import IObjectQuery
 from ocql.interfaces import IOptimizedObjectQuery
 from ocql.interfaces import IAlgebraObject
 from ocql.interfaces import IOptimizedAlgebraObject
 from ocql.interfaces import IRunnableQuery
+from ocql.interfaces import IObjectQueryHead
 
 class OCQLEngine:
     implements(IEngine)
@@ -32,11 +32,14 @@
     def compile(self, query):
         #TODO: later use maybe named adapters
         metadata = IDB(None)
-
-        objectquery = IQueryParser(query)(metadata)
+        if IObjectQueryHead.providedBy(query):
+            objectquery = query
+        else:
+            objectquery = IQueryParser(query)(metadata)
+        
         optimizedoq = IQueryOptimizer(objectquery)()
         algebra = IRewriter(optimizedoq)()
-        optimizedalgebra = IAlgebraOptimizer(algebra)()
-        runnable = IAlgebraCompiler(optimizedalgebra)(metadata, algebra)
+        optimizedalgebra = IAlgebraOptimizer(algebra)(metadata)
+        runnable = IAlgebraCompiler(optimizedalgebra)(metadata, optimizedalgebra)
 
-        return runnable
\ No newline at end of file
+        return runnable

Deleted: Sandbox/adamg/ocql/trunk/src/ocql/parser/queryparser.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/parser/queryparser.py	2008-08-08 09:04:59 UTC (rev 89533)
+++ Sandbox/adamg/ocql/trunk/src/ocql/parser/queryparser.py	2008-08-08 09:13:02 UTC (rev 89534)
@@ -1,651 +0,0 @@
-# -*- coding: UTF-8 -*-
-
-"""Parse a string to Query Object
-
-"""
-
-#TODOs:
-#add metadata into the picture!!!
-#remove shift/reduce conflicts, when possible
-#look after raise "Help"
-#revise according to new grammar
-
-from ply import lex, yacc
-from collections import deque
-from threading import local
-
-from zope.component import adapts
-from zope.component import provideAdapter
-from zope.interface import implements
-
-from ocql.queryobject.queryobject import *
-from ocql.interfaces import IQueryParser
-
-DEBUG = 0
-
-class SymbolContainer:
-    def __init__(self):
-        self.stack = deque()
-        self.stack.append(dict())
-
-    def addlevel(self):
-        top = self.current()
-        new = dict(top)
-        self.stack.append(new)
-
-    def dellevel(self):
-        self.stack.pop()
-
-    def current(self):
-        return self.stack[-1]
-
-tokens = ('SET', 'LIST', 'COMMA', 'NOT_EQUAL', 'UNION', 'AS', 'EVERY', 'ATMOST', 'LT', 'GT', 'ELLIPSIS', 'BRACKET_R', 'OR', 'PIPE', 'DOT', 'IN', 'LTE', 'SOME', 'AND', 'CBRACKET_L', 'CONSTANT', 'EQUAL', 'GTE', 'ISINSTANCE', 'SEMI_COLON', 'BRACKET_L', 'ASSIGN', 'NOT_ASSIGN', 'FOR', 'CBRACKET_R', 'JUST', 'IDENTIFIER', 'DIFFER', 'LEN', 'BAG', 'SBRACKET_L', 'NOT', 'ATLEAST', 'SBRACKET_R')
-
-precedence = (
-    ('left', 'UNION'),
-    ('left', 'DIFFER'),
-#   ('token', 'SQUAREL'),
-#   ('token', 'PIPE'),
-#   ('token', 'SQUARER'),
-    ('left', 'AND'),
-    ('left', 'OR'),
-    ('right', 'NOT'),
-    #('left', 'COND_OP'),
-#    ('left', 'PLUS', 'MINUS'),
-#    ('left', 'MUL', 'DIV'),
-#   ('token', 'IDENTIFIER'),
-#   ('token', 'BRACEL'),
-#   ('token', 'BRACER'),
-#   ('token', 'CONSTANT'),
-#   ('token', 'TYPE'),
-#   ('token', 'CURLYL'),
-#   ('token', 'CURLYR'),
-#   ('token', 'ELLIPSIS'),
-    ('left', 'DOT'),
-#   ('token', 'COMMA'),
-    ('left', 'SEMI_COLON'),
-
-    ('left', 'IN'),
-    ('left', 'AS'),
-
-#   ('token', 'MODIFIER'),
-#   ('token', 'QUANTOR'),
-
-#    ('left', 'SIZE'),
-)
-
-class Lexer(object):
-    tokens = tokens
-    t_ignore = ' \t\n\r'
-
-    def t_error(self, t):
-        print "Illegal character '%s'" % t.value[0]
-        t.lexer.skip(1)
-
-    def t_UNION(self, t):
-        r'union'
-        return t
-
-    def t_DIFFER(self, t):
-        r'differ'
-        return t
-
-    def t_SET(self, t):
-        r'set'
-        return t
-
-    def t_LIST(self, t):
-        r'list'
-        return t
-
-    def t_BAG(self, t):
-        r'bag'
-        return t
-
-    def t_FOR(self, t):
-        r'for'
-        return t
-
-    def t_LEN(self, t):
-        r'len'
-        return t
-
-    def t_AS(self, t):
-        r'as'
-        return t
-
-    def t_IN(self, t):
-        r'in'
-        return t
-
-    def t_OR(self, t):
-        r'or'
-        return t
-
-    def t_AND(self, t):
-        r'and'
-        return t
-
-    def t_NOT(self, t):
-        r'not'
-        return t
-
-    def t_ISINSTANCE(self, t):
-        r'isinstance'
-        return t
-
-    def t_EVERY(self, t):
-        r'every'
-        return t
-
-    def t_ATMOST(self, t):
-        r'atmost'
-        return t
-
-    def t_ATLEAST(self, t):
-        r'atleast'
-        return t
-
-    def t_SOME(self, t):
-        r'some'
-        return t
-
-    def t_JUST(self, t):
-        r'just'
-        return t
-
-    def t_CONSTANT(self, t):
-        r'(\'(\\.|[^\'])*\'|"(\\.|[^"])*"|[0-9]+)'
-        return t
-
-    def t_IDENTIFIER(self, t):
-        r'[a-zA-Z][0-9a-zA-Z_]*'
-        return t
-
-    def t_COMMA(self, t):
-        r','
-        return t
-
-#this may be != sign
-    def t_NOT_EQUAL(self, t):
-        r'~=='
-        return t
-
-    def t_LT(self, t):
-        r'<'
-        return t
-
-    def t_GT(self, t):
-        r'>'
-        return t
-
-    def t_ELLIPSIS(self, t):
-        r'\.\.\.'
-        return t
-
-    def t_PIPE(self, t):
-        r'\|'
-        return t
-
-    def t_DOT(self, t):
-        r'\.'
-        return t
-
-    def t_MUL(self, t):
-        r'\*'
-        return t
-
-    def t_CBRACKET_L(self, t):
-        r'{'
-        return t
-
-    def t_CBRACKET_R(self, t):
-        r'}'
-        return t
-
-    def t_EQUAL(self, t):
-        r'=='
-        return t
-
-    def t_GTE(self, t):
-        r'>='
-        return t
-
-    def t_LTE(self, t):
-        r'<='
-        return t
-
-    def t_SEMI_COLON(self, t):
-        r';'
-        return t
-
-    def t_BRACKET_L(self, t):
-        r'\('
-        return t
-
-    def t_BRACKET_R(self, t):
-        r'\)'
-        return t
-
-    def t_ASSIGN(self, t):
-        r'='
-        return t
-
-    def t_NOT_ASSIGN(self, t):
-        r'~='
-        return t
-
-#    def t_DIV(self, t):
-#        r'/'
-#        return t
-
-#    def t_PLUS(self, t):
-#        r'\+'
-#        return t
-
-#    def t_MINUS(self, t):
-#        r'-'
-#        return t
-
-    def t_SBRACKET_L(self, t):
-        r'\['
-        return t
-
-    def t_SBRACKET_R(self, t):
-        r'\]'
-        return t
-
-
-
-class Parser(object):
-    tokens = tokens
-    precedence = precedence
-    metadata = None
-    symbols = None
-    types = { 'set' : set, 'list': list }
-    start = 'expression'
-
-    def __init__(self, metadata):
-        self.metadata = metadata
-        self.symbols = SymbolContainer()
-
-    def p_error(self, t):
-        print "Syntax error at '%s' (%s)" % (t.value, t.lexpos)
-
-    def p_expr_union(self, t):
-        r'''expression : expression UNION expression
-        '''
-        t[0] = Union(self.metadata, self.symbols, t[1], t[3])
-        if DEBUG: print 'reducing "expression UNION expression" to "expression"', t[0]
-
-    def p_expr_differ(self, t):
-        r'''expression : expression DIFFER expression
-        '''
-        t[0] = Differ(self.metadata, self.symbols, t[1], t[3])
-        if DEBUG: print 'reducing "expression DIFFER expression" to "expression"', t[0]
-
-#    def p_expr_3(self, t):
-#        r'''expression : collection SBRACKET_L expression SBRACKET_R
-#        '''
-#        t[0] = Query(self.metadata, self.symbols, t[1], [], t[3])
-#        if DEBUG: print 'reducing "collection SBRACKET_L qualifier PIPE expression SBRACKET_R" to "expression"'
-
-    def p_expr_query(self, t):
-        r'''expression : collection SBRACKET_L qualifier PIPE expression SBRACKET_R
-        '''
-        t[0] = Query(self.metadata, self.symbols, t[1], t[3], t[5])
-        if DEBUG: print 'reducing "collection SBRACKET_L qualifier PIPE expression SBRACKET_R" to "expression"', t[0]
-
-#TODO add a test
-    def p_expr_for_query(self, t):
-        r'''expression : collection SBRACKET_L qualifier FOR expression SBRACKET_R
-        '''
-        t[0] = Query(self.metadata, self.symbols, t[1], t[3], t[5])
-        if DEBUG: print 'reducing "collection SBRACKET_L qualifier FOR expression SBRACKET_R" to "expression"', t[0]
-
-    def p_expr_literal(self, t):
-        r'''expression : literal
-        '''
-        t[0] = t[1]
-        if DEBUG: print 'reducing "literal" to "expression"', t[0]
-
-    def p_expr_path(self, t):
-        r'''expression : path
-        '''
-        t[0] = t[1]
-        if DEBUG: print 'reducing "path" to "expression"', t[0]
-
-    def p_expr_call(self, t):
-        r'''expression : call
-        '''
-        t[0] = t[1]
-        if DEBUG: print 'reducing "path" to "expression"', t[0]
-
-    def p_expr_len(self, t):
-        r'''expression : LEN BRACKET_L expression BRACKET_R
-        '''
-        t[0] = Count(self.metadata, self.symbols, t[3])
-        if DEBUG: print 'reducing "LEN BRACKET_L expression BRACKET_R" to "expression"', t[0]
-
-    def p_collection_set(self, t):
-        r'''collection : SET
-        '''
-        t[0] = self.types['set']
-        if DEBUG: print 'reducing "set" to "collection"', t[0]
-
-    def p_collection_list(self, t):
-        r'''collection : LIST
-        '''
-        t[0] = self.types['list']
-        if DEBUG: print 'reducing "list" to "collection"', t[0]
-
-    def p_collection_bag(self, t):
-        r'''collection : BAG
-        '''
-        raise NotImplementedError('bag')
-        if DEBUG: print 'reducing "bag" to "collection"', t[0]
-
-    def p_qualifier_null(self, t):
-        r'''qualifier :
-        '''
-        t[0] = []
-        if DEBUG: print 'reducing "" to "qualifier"', t[0]
-
-    def p_qualifier_generator(self, t):
-        r'''qualifier : generator
-        '''
-        t[0] = [t[1]]
-        if DEBUG: print 'reducing "generator" to "qualifier"', t[0]
-
-    def p_qualifier_definition(self, t):
-        r'''qualifier : definition
-        '''
-        t[0] = [t[1]]
-        if DEBUG: print 'reducing "definition" to "qualifier"', t[0]
-
-    def p_qualifier_filter(self, t):
-        r'''qualifier : filter
-        '''
-        t[0] = [t[1]]
-        if DEBUG: print 'reducing "filter" to "qualifier"', t[0]
-
-    def p_qualifier_qualifier(self, t):
-        r'''qualifier : qualifier SEMI_COLON qualifier
-        '''
-        t[0] = t[0].extend(t[1])
-        t[0] = t[0].extend(t[3])
-        if DEBUG: print 'reducing "qualifier SEMI_COLON qualifier" to "qualifier"', t[0]
-
-#    def p_qualifier_6(self, t):
-#        r'''qualifier : expression
-#        '''
-#        t[0] = t[1]
-#        if DEBUG: print 'reducing "expression" to "qualifier"'
-
-    def p_generator_in(self, t):
-        r'''generator : IDENTIFIER IN expression
-        '''
-        t[0] = In(self.metadata,
-                  self.symbols,
-                  Identifier(self.metadata,
-                             self.symbols,
-                             t[1]),
-                  t[3])
-        if DEBUG: print 'reducing "IDENTIFIER IN expression" to "generator"', t[0]
-
-    def p_filter_and(self, t):
-        r'''filter : filter AND filter
-        '''
-        t[0] = And(self.metadata, self.symbols, t[1], t[3])
-        if DEBUG: print 'reducing "filter AND filter" to "filter"', t[0]
-
-    def p_filter_or(self, t):
-        r'''filter : filter OR filter
-        '''
-        t[0] = Or(self.metadata, self.symbols, t[1], t[3])
-        if DEBUG: print 'reducing "filter OR filter" to "filter"', t[0]
-
-    def p_filter_not(self, t):
-        r'''filter : NOT condition
-        '''
-        t[0] = Not(self.metadata, self.symbols, t[1], t[3])
-        if DEBUG: print 'reducing "NOT condition" to "filter"', t[0]
-
-    def p_filter_condition(self, t):
-        r'''filter : condition
-        '''
-        t[0] = t[1]
-        if DEBUG: print 'reducing "condition" to "filter"', t[0]
-
-    def p_condition_filter(self, t):
-        r'''condition : BRACKET_L filter BRACKET_R
-        '''
-        t[0] = t[2]
-        if DEBUG: print 'reducing "BRACKET_L filter BRACKET_R" to "condition"', t[0]
-
-    def p_condition_assign(self, t):
-        r'''condition : quantified ASSIGN quantified
-        '''
-        raise NotImplementedError('assign')
-        if DEBUG: print 'reducing "quantified operator quantified" to "condition"', t[0]
-
-    def p_condition_not_assign(self, t):
-        r'''condition : quantified NOT_ASSIGN quantified
-        '''
-        raise NotImplementedError('not assign')
-        if DEBUG: print 'reducing "quantified operator quantified" to "condition"', t[0]
-
-    def p_condition_lt(self, t):
-        r'''condition : quantified LT quantified
-        '''
-        t[0] = Lt(self.metadata, self.symbols, t[1], t[3])
-        if DEBUG: print 'reducing "quantified operator quantified" to "condition"', t[0]
-
-    def p_condition_lte(self, t):
-        r'''condition : quantified LTE quantified
-        '''
-        t[0] = Le(self.metadata, self.symbols, t[1], t[3])
-        if DEBUG: print 'reducing "quantified operator quantified" to "condition"', t[0]
-
-    def p_condition_gt(self, t):
-        r'''condition : quantified GT quantified
-        '''
-        t[0] = Gt(self.metadata, self.symbols, t[1], t[3])
-        if DEBUG: print 'reducing "quantified operator quantified" to "condition"', t[0]
-
-    def p_condition_gte(self, t):
-        r'''condition : quantified GTE quantified
-        '''
-        t[0] = Ge(self.metadata, self.symbols, t[1], t[3])
-        if DEBUG: print 'reducing "quantified operator quantified" to "condition"', t[0]
-
-    def p_condition_equal(self, t):
-        r'''condition : quantified EQUAL quantified
-        '''
-        t[0] = Eq(self.metadata, self.symbols, t[1], t[3])
-        if DEBUG: print 'reducing "quantified operator quantified" to "condition"', t[0]
-
-    def p_condition_not_equal(self, t):
-        r'''condition : quantified  NOT_EQUAL quantified
-        '''
-        t[0] = Ne(self.metadata, self.symbols, t[1], t[3])
-        if DEBUG: print 'reducing "quantified operator quantified" to "condition"', t[0]
-
-    #need to extend this for collection of types
-    def p_condition_isinstance(self, t):
-        r'''condition : ISINSTANCE BRACKET_L expression COMMA IDENTIFIER BRACKET_R
-        '''
-        raise NotImplementedError('isinstance')
-        if DEBUG: print 'reducing "ISINSTANCE BRACKET_L expression COMMA IDENTIFIER BRACKET_R" to "condition"', t[0]
-
-    def p_quantified_expression(self, t):
-        r'''quantified : expression
-        '''
-        t[0] = t[1]
-        if DEBUG: print 'reducing "expression" to "quantified"', t[0]
-
-    def p_quantified_some(self, t):
-        r'''quantified : SOME expression
-        '''
-        t[0] = Some(self.metadata, self.symbols, t[2])
-        if DEBUG: print 'reducing "quantification expression" to "quantified"', t[0]
-
-    def p_quantified_just(self, t):
-        r'''quantified : JUST expression
-        '''
-        t[0] = Just(self.metadata, self.symbols, t[2])
-        if DEBUG: print 'reducing "quantification expression" to "quantified"', t[0]
-
-    def p_quantified_every(self, t):
-        r'''quantified : EVERY expression
-        '''
-        t[0] = Every(self.metadata, self.symbols, t[2])
-        if DEBUG: print 'reducing "quantification expression" to "quantified"', t[0]
-
-    def p_quantified_atleast(self, t):
-        r'''quantified : ATLEAST expression
-        '''
-        t[0] = Atleast(self.metadata, self.symbols, t[2])
-        if DEBUG: print 'reducing "quantification expression" to "quantified"', t[0]
-
-    def p_quantified_almost(self, t):
-        r'''quantified : ATMOST expression
-        '''
-        t[0] = Atmost(self.metadata, self.symbols, t[2])
-        if DEBUG: print 'reducing "quantification expression" to "quantified"', t[0]
-
-    def p_definition_as(self, t):
-        r'''definition : IDENTIFIER AS expression
-        '''
-        #t[0]=''
-        if DEBUG: print 'reducing "IDENTIFIER AS expression" to "definition"', t[0]
-
-    def p_literal_constant(self, t):
-        r'''literal : CONSTANT
-        '''
-        t[0] = Constant(self.metadata, self.symbols, t[1])
-        if DEBUG: print 'reducing "CONSTANT" to "literal"', t[0]
-
-    def p_literal_element(self, t):
-        r'''literal : collection CBRACKET_L element CBRACKET_R
-        '''
-        raise NotImplementedError('collection set')
-        if DEBUG: print 'reducing "collection CBRACKET_L element CBRACKET_R" to "literal"', t[0]
-
-    def p_element_null(self, t):
-        r'''element :
-        '''
-        t[0] = None
-        if DEBUG: print 'reducing "" to "element"', t[0]
-
-    def p_element_expression(self, t):
-        r'''element : expression
-        '''
-        t[0] = t[1]
-        if DEBUG: print 'reducing "expression" to "element"', t[0]
-
-# Why this raise a shift/reduce conflict
-#    def p_element_comma(self, t):
-#        r'''element : element COMMA element
-#        '''
-#        raise NotImplementedError('element list')
-#        if DEBUG: print 'reducing "element COMMA element" to "element"', t[0]
-
-    def p_element_ellipsis(self, t):
-        r'''element : expression ELLIPSIS expression
-        '''
-        raise NotImplementedError('range')
-        if DEBUG: print 'reducing "expression ELLIPSIS expression" to "element"', t[0]
-
-    def p_path_identifier(self, t):
-        r'''path : IDENTIFIER
-        '''
-        t[0] = Identifier(self.metadata, self.symbols, t[1])
-        if DEBUG: print 'reducing "IDENTIFIER" to "path"', t[0]
-
-    def p_path_method(self, t):
-        r'''path : IDENTIFIER DOT method
-        '''
-        t[0] = Property(self.metadata, self.symbols, Identifier(self.metadata, self.symbols, t[1]), t[3])
-        if DEBUG: print 'reducing "IDENTIFIER DOT method" to "path"', t[0]
-
-    def p_method_identifier(self, t):
-        r'''method : IDENTIFIER
-        '''
-        t[0] = Identifier(self.metadata, self.symbols, t[1])
-        if DEBUG: print 'reducing "IDENTIFIER" to "method"', t[0]
-
-    def p_method_arguments(self, t):
-        r'''method : IDENTIFIER BRACKET_L argument_list BRACKET_R
-        '''
-        raise NotImplementedError('function call')
-        if DEBUG: print 'reducing "IDENTIFIER BRACKET_L argument_list BRACKET_R" to "method"', t[0]
-
-    def p_argument_list_null(self, t):
-        r'''argument_list :
-        '''
-        t[0] = None
-        if DEBUG: print 'reducing "" to "argument_list"', t[0]
-
-    def p_argument_list_expression(self, t):
-        r'''argument_list : expression
-        '''
-        t[0] = t[1]
-        if DEBUG: print 'reducing "expression" to "argument_list"', t[0]
-
-    def p_argument_list_set(self, t):
-        r'''argument_list : expression COMMA argument_list
-        '''
-        t[0]=''
-        if DEBUG: print 'reducing "expression COMMA argument_list" to "argument_list"', t[0]
-
-    def p_call(self, t):
-        r'''call : IDENTIFIER BRACKET_L argument_list BRACKET_R
-        '''
-        raise NotImplementedError('function call')
-        if DEBUG: print 'reducing "IDENTIFIER BRACKET_L argument_list BRACKET_R" to "call"', t[0]
-
-#these are here, to keep lexer and parser instantiation to a minimum possible
-#level because they are quite expensive operations
-#parsers must be thread safe on the other hand!
-LEXER = lex.lex(object=Lexer(), debug=0)
-#PARSERS = local()
-
-def parse(str, metadata):
-    lexer = LEXER.clone()
-
-    #global PARSERS
-    #try:
-    #    parser = PARSERS.parser
-    #
-    #    try:
-    #        parser.restart()
-    #    except AttributeError:
-    #        pass
-    #
-    #except AttributeError:
-    #    parser = yacc.yacc(module = Parser(metadata))
-    #    PARSERS.parser = parser
-
-    try:
-        parser = yacc.yacc(module = Parser(metadata))
-
-        retval = parser.parse(str, lexer = lexer)
-    except Exception, e:
-        if DEBUG: print e
-        raise
-    return retval
-
-class QueryParser(object):
-    implements(IQueryParser)
-    adapts(basestring)
-
-    def __init__(self, context):
-        self.context = context
-        #self.db = db
-
-    def __call__(self, metadata):
-        strg = self.context
-        tree = parse(strg, metadata)
-        return Head(tree)
-        #return parse(strg, None)
\ No newline at end of file

Copied: Sandbox/adamg/ocql/trunk/src/ocql/parser/queryparser.py (from rev 89533, Sandbox/adamg/ocql/branches/optimize-with-index/src/ocql/parser/queryparser.py)
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/parser/queryparser.py	                        (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/parser/queryparser.py	2008-08-08 09:13:02 UTC (rev 89534)
@@ -0,0 +1,651 @@
+# -*- coding: UTF-8 -*-
+
+"""Parse a string to Query Object
+
+"""
+
+#TODOs:
+#add metadata into the picture!!!
+#remove shift/reduce conflicts, when possible
+#look after raise "Help"
+#revise according to new grammar
+
+from ply import lex, yacc
+from collections import deque
+from threading import local
+
+from zope.component import adapts
+from zope.component import provideAdapter
+from zope.interface import implements
+
+from ocql.queryobject.queryobject import *
+from ocql.interfaces import IQueryParser
+
+DEBUG = 0
+
+class SymbolContainer:
+    def __init__(self):
+        self.stack = deque()
+        self.stack.append(dict())
+
+    def addlevel(self):
+        top = self.current()
+        new = dict(top)
+        self.stack.append(new)
+
+    def dellevel(self):
+        self.stack.pop()
+
+    def current(self):
+        return self.stack[-1]
+
+tokens = ('SET', 'LIST', 'COMMA', 'NOT_EQUAL', 'UNION', 'AS', 'EVERY', 'ATMOST', 'LT', 'GT', 'ELLIPSIS', 'BRACKET_R', 'OR', 'PIPE', 'DOT', 'IN', 'LTE', 'SOME', 'AND', 'CBRACKET_L', 'CONSTANT', 'EQUAL', 'GTE', 'ISINSTANCE', 'SEMI_COLON', 'BRACKET_L', 'ASSIGN', 'NOT_ASSIGN', 'FOR', 'CBRACKET_R', 'JUST', 'IDENTIFIER', 'DIFFER', 'LEN', 'BAG', 'SBRACKET_L', 'NOT', 'ATLEAST', 'SBRACKET_R')
+
+precedence = (
+    ('left', 'UNION'),
+    ('left', 'DIFFER'),
+#   ('token', 'SQUAREL'),
+#   ('token', 'PIPE'),
+#   ('token', 'SQUARER'),
+    ('left', 'AND'),
+    ('left', 'OR'),
+    ('right', 'NOT'),
+    #('left', 'COND_OP'),
+#    ('left', 'PLUS', 'MINUS'),
+#    ('left', 'MUL', 'DIV'),
+#   ('token', 'IDENTIFIER'),
+#   ('token', 'BRACEL'),
+#   ('token', 'BRACER'),
+#   ('token', 'CONSTANT'),
+#   ('token', 'TYPE'),
+#   ('token', 'CURLYL'),
+#   ('token', 'CURLYR'),
+#   ('token', 'ELLIPSIS'),
+    ('left', 'DOT'),
+#   ('token', 'COMMA'),
+    ('left', 'SEMI_COLON'),
+
+    ('left', 'IN'),
+    ('left', 'AS'),
+
+#   ('token', 'MODIFIER'),
+#   ('token', 'QUANTOR'),
+
+#    ('left', 'SIZE'),
+)
+
+class Lexer(object):
+    tokens = tokens
+    t_ignore = ' \t\n\r'
+
+    def t_error(self, t):
+        print "Illegal character '%s'" % t.value[0]
+        t.lexer.skip(1)
+
+    def t_UNION(self, t):
+        r'union'
+        return t
+
+    def t_DIFFER(self, t):
+        r'differ'
+        return t
+
+    def t_SET(self, t):
+        r'set'
+        return t
+
+    def t_LIST(self, t):
+        r'list'
+        return t
+
+    def t_BAG(self, t):
+        r'bag'
+        return t
+
+    def t_FOR(self, t):
+        r'for'
+        return t
+
+    def t_LEN(self, t):
+        r'len'
+        return t
+
+    def t_AS(self, t):
+        r'as'
+        return t
+
+    def t_IN(self, t):
+        r'in'
+        return t
+
+    def t_OR(self, t):
+        r'or'
+        return t
+
+    def t_AND(self, t):
+        r'and'
+        return t
+
+    def t_NOT(self, t):
+        r'not'
+        return t
+
+    def t_ISINSTANCE(self, t):
+        r'isinstance'
+        return t
+
+    def t_EVERY(self, t):
+        r'every'
+        return t
+
+    def t_ATMOST(self, t):
+        r'atmost'
+        return t
+
+    def t_ATLEAST(self, t):
+        r'atleast'
+        return t
+
+    def t_SOME(self, t):
+        r'some'
+        return t
+
+    def t_JUST(self, t):
+        r'just'
+        return t
+
+    def t_CONSTANT(self, t):
+        r'(\'(\\.|[^\'])*\'|"(\\.|[^"])*"|[0-9]+)'
+        return t
+
+    def t_IDENTIFIER(self, t):
+        r'[a-zA-Z][0-9a-zA-Z_]*'
+        return t
+
+    def t_COMMA(self, t):
+        r','
+        return t
+
+#this may be != sign
+    def t_NOT_EQUAL(self, t):
+        r'~=='
+        return t
+
+    def t_LT(self, t):
+        r'<'
+        return t
+
+    def t_GT(self, t):
+        r'>'
+        return t
+
+    def t_ELLIPSIS(self, t):
+        r'\.\.\.'
+        return t
+
+    def t_PIPE(self, t):
+        r'\|'
+        return t
+
+    def t_DOT(self, t):
+        r'\.'
+        return t
+
+    def t_MUL(self, t):
+        r'\*'
+        return t
+
+    def t_CBRACKET_L(self, t):
+        r'{'
+        return t
+
+    def t_CBRACKET_R(self, t):
+        r'}'
+        return t
+
+    def t_EQUAL(self, t):
+        r'=='
+        return t
+
+    def t_GTE(self, t):
+        r'>='
+        return t
+
+    def t_LTE(self, t):
+        r'<='
+        return t
+
+    def t_SEMI_COLON(self, t):
+        r';'
+        return t
+
+    def t_BRACKET_L(self, t):
+        r'\('
+        return t
+
+    def t_BRACKET_R(self, t):
+        r'\)'
+        return t
+
+    def t_ASSIGN(self, t):
+        r'='
+        return t
+
+    def t_NOT_ASSIGN(self, t):
+        r'~='
+        return t
+
+#    def t_DIV(self, t):
+#        r'/'
+#        return t
+
+#    def t_PLUS(self, t):
+#        r'\+'
+#        return t
+
+#    def t_MINUS(self, t):
+#        r'-'
+#        return t
+
+    def t_SBRACKET_L(self, t):
+        r'\['
+        return t
+
+    def t_SBRACKET_R(self, t):
+        r'\]'
+        return t
+
+
+
+class Parser(object):
+    tokens = tokens
+    precedence = precedence
+    metadata = None
+    symbols = None
+    types = { 'set' : set, 'list': list }
+    start = 'expression'
+
+    def __init__(self, metadata):
+        self.metadata = metadata
+        self.symbols = SymbolContainer()
+
+    def p_error(self, t):
+        print "Syntax error at '%s' (%s)" % (t.value, t.lexpos)
+
+    def p_expr_union(self, t):
+        r'''expression : expression UNION expression
+        '''
+        t[0] = Union(self.metadata, self.symbols, t[1], t[3])
+        if DEBUG: print 'reducing "expression UNION expression" to "expression"', t[0]
+
+    def p_expr_differ(self, t):
+        r'''expression : expression DIFFER expression
+        '''
+        t[0] = Differ(self.metadata, self.symbols, t[1], t[3])
+        if DEBUG: print 'reducing "expression DIFFER expression" to "expression"', t[0]
+
+#    def p_expr_3(self, t):
+#        r'''expression : collection SBRACKET_L expression SBRACKET_R
+#        '''
+#        t[0] = Query(self.metadata, self.symbols, t[1], [], t[3])
+#        if DEBUG: print 'reducing "collection SBRACKET_L qualifier PIPE expression SBRACKET_R" to "expression"'
+
+    def p_expr_query(self, t):
+        r'''expression : collection SBRACKET_L qualifier PIPE expression SBRACKET_R
+        '''
+        t[0] = Query(self.metadata, self.symbols, t[1], t[3], t[5])
+        if DEBUG: print 'reducing "collection SBRACKET_L qualifier PIPE expression SBRACKET_R" to "expression"', t[0]
+
+#TODO add a test
+    def p_expr_for_query(self, t):
+        r'''expression : collection SBRACKET_L qualifier FOR expression SBRACKET_R
+        '''
+        t[0] = Query(self.metadata, self.symbols, t[1], t[3], t[5])
+        if DEBUG: print 'reducing "collection SBRACKET_L qualifier FOR expression SBRACKET_R" to "expression"', t[0]
+
+    def p_expr_literal(self, t):
+        r'''expression : literal
+        '''
+        t[0] = t[1]
+        if DEBUG: print 'reducing "literal" to "expression"', t[0]
+
+    def p_expr_path(self, t):
+        r'''expression : path
+        '''
+        t[0] = t[1]
+        if DEBUG: print 'reducing "path" to "expression"', t[0]
+
+    def p_expr_call(self, t):
+        r'''expression : call
+        '''
+        t[0] = t[1]
+        if DEBUG: print 'reducing "path" to "expression"', t[0]
+
+    def p_expr_len(self, t):
+        r'''expression : LEN BRACKET_L expression BRACKET_R
+        '''
+        t[0] = Count(self.metadata, self.symbols, t[3])
+        if DEBUG: print 'reducing "LEN BRACKET_L expression BRACKET_R" to "expression"', t[0]
+
+    def p_collection_set(self, t):
+        r'''collection : SET
+        '''
+        t[0] = self.types['set']
+        if DEBUG: print 'reducing "set" to "collection"', t[0]
+
+    def p_collection_list(self, t):
+        r'''collection : LIST
+        '''
+        t[0] = self.types['list']
+        if DEBUG: print 'reducing "list" to "collection"', t[0]
+
+    def p_collection_bag(self, t):
+        r'''collection : BAG
+        '''
+        raise NotImplementedError('bag')
+        if DEBUG: print 'reducing "bag" to "collection"', t[0]
+
+    def p_qualifier_null(self, t):
+        r'''qualifier :
+        '''
+        t[0] = []
+        if DEBUG: print 'reducing "" to "qualifier"', t[0]
+
+    def p_qualifier_generator(self, t):
+        r'''qualifier : generator
+        '''
+        t[0] = [t[1]]
+        if DEBUG: print 'reducing "generator" to "qualifier"', t[0]
+
+    def p_qualifier_definition(self, t):
+        r'''qualifier : definition
+        '''
+        t[0] = [t[1]]
+        if DEBUG: print 'reducing "definition" to "qualifier"', t[0]
+
+    def p_qualifier_filter(self, t):
+        r'''qualifier : filter
+        '''
+        t[0] = [t[1]]
+        if DEBUG: print 'reducing "filter" to "qualifier"', t[0]
+
+    def p_qualifier_qualifier(self, t):
+        r'''qualifier : qualifier SEMI_COLON qualifier
+        '''
+        t[0] = t[0].extend(t[1])
+        t[0] = t[0].extend(t[3])
+        if DEBUG: print 'reducing "qualifier SEMI_COLON qualifier" to "qualifier"', t[0]
+
+#    def p_qualifier_6(self, t):
+#        r'''qualifier : expression
+#        '''
+#        t[0] = t[1]
+#        if DEBUG: print 'reducing "expression" to "qualifier"'
+
+    def p_generator_in(self, t):
+        r'''generator : IDENTIFIER IN expression
+        '''
+        t[0] = In(self.metadata,
+                  self.symbols,
+                  Identifier(self.metadata,
+                             self.symbols,
+                             t[1]),
+                  t[3])
+        if DEBUG: print 'reducing "IDENTIFIER IN expression" to "generator"', t[0]
+
+    def p_filter_and(self, t):
+        r'''filter : filter AND filter
+        '''
+        t[0] = And(self.metadata, self.symbols, t[1], t[3])
+        if DEBUG: print 'reducing "filter AND filter" to "filter"', t[0]
+
+    def p_filter_or(self, t):
+        r'''filter : filter OR filter
+        '''
+        t[0] = Or(self.metadata, self.symbols, t[1], t[3])
+        if DEBUG: print 'reducing "filter OR filter" to "filter"', t[0]
+
+    def p_filter_not(self, t):
+        r'''filter : NOT condition
+        '''
+        t[0] = Not(self.metadata, self.symbols, t[1], t[3])
+        if DEBUG: print 'reducing "NOT condition" to "filter"', t[0]
+
+    def p_filter_condition(self, t):
+        r'''filter : condition
+        '''
+        t[0] = t[1]
+        if DEBUG: print 'reducing "condition" to "filter"', t[0]
+
+    def p_condition_filter(self, t):
+        r'''condition : BRACKET_L filter BRACKET_R
+        '''
+        t[0] = t[2]
+        if DEBUG: print 'reducing "BRACKET_L filter BRACKET_R" to "condition"', t[0]
+
+    def p_condition_assign(self, t):
+        r'''condition : quantified ASSIGN quantified
+        '''
+        raise NotImplementedError('assign')
+        if DEBUG: print 'reducing "quantified operator quantified" to "condition"', t[0]
+
+    def p_condition_not_assign(self, t):
+        r'''condition : quantified NOT_ASSIGN quantified
+        '''
+        raise NotImplementedError('not assign')
+        if DEBUG: print 'reducing "quantified operator quantified" to "condition"', t[0]
+
+    def p_condition_lt(self, t):
+        r'''condition : quantified LT quantified
+        '''
+        t[0] = Lt(self.metadata, self.symbols, t[1], t[3])
+        if DEBUG: print 'reducing "quantified operator quantified" to "condition"', t[0]
+
+    def p_condition_lte(self, t):
+        r'''condition : quantified LTE quantified
+        '''
+        t[0] = Le(self.metadata, self.symbols, t[1], t[3])
+        if DEBUG: print 'reducing "quantified operator quantified" to "condition"', t[0]
+
+    def p_condition_gt(self, t):
+        r'''condition : quantified GT quantified
+        '''
+        t[0] = Gt(self.metadata, self.symbols, t[1], t[3])
+        if DEBUG: print 'reducing "quantified operator quantified" to "condition"', t[0]
+
+    def p_condition_gte(self, t):
+        r'''condition : quantified GTE quantified
+        '''
+        t[0] = Ge(self.metadata, self.symbols, t[1], t[3])
+        if DEBUG: print 'reducing "quantified operator quantified" to "condition"', t[0]
+
+    def p_condition_equal(self, t):
+        r'''condition : quantified EQUAL quantified
+        '''
+        t[0] = Eq(self.metadata, self.symbols, t[1], t[3])
+        if DEBUG: print 'reducing "quantified operator quantified" to "condition"', t[0]
+
+    def p_condition_not_equal(self, t):
+        r'''condition : quantified  NOT_EQUAL quantified
+        '''
+        t[0] = Ne(self.metadata, self.symbols, t[1], t[3])
+        if DEBUG: print 'reducing "quantified operator quantified" to "condition"', t[0]
+
+    #need to extend this for collection of types
+    def p_condition_isinstance(self, t):
+        r'''condition : ISINSTANCE BRACKET_L expression COMMA IDENTIFIER BRACKET_R
+        '''
+        raise NotImplementedError('isinstance')
+        if DEBUG: print 'reducing "ISINSTANCE BRACKET_L expression COMMA IDENTIFIER BRACKET_R" to "condition"', t[0]
+
+    def p_quantified_expression(self, t):
+        r'''quantified : expression
+        '''
+        t[0] = t[1]
+        if DEBUG: print 'reducing "expression" to "quantified"', t[0]
+
+    def p_quantified_some(self, t):
+        r'''quantified : SOME expression
+        '''
+        t[0] = Some(self.metadata, self.symbols, t[2])
+        if DEBUG: print 'reducing "quantification expression" to "quantified"', t[0]
+
+    def p_quantified_just(self, t):
+        r'''quantified : JUST expression
+        '''
+        t[0] = Just(self.metadata, self.symbols, t[2])
+        if DEBUG: print 'reducing "quantification expression" to "quantified"', t[0]
+
+    def p_quantified_every(self, t):
+        r'''quantified : EVERY expression
+        '''
+        t[0] = Every(self.metadata, self.symbols, t[2])
+        if DEBUG: print 'reducing "quantification expression" to "quantified"', t[0]
+
+    def p_quantified_atleast(self, t):
+        r'''quantified : ATLEAST expression
+        '''
+        t[0] = Atleast(self.metadata, self.symbols, t[2])
+        if DEBUG: print 'reducing "quantification expression" to "quantified"', t[0]
+
+    def p_quantified_almost(self, t):
+        r'''quantified : ATMOST expression
+        '''
+        t[0] = Atmost(self.metadata, self.symbols, t[2])
+        if DEBUG: print 'reducing "quantification expression" to "quantified"', t[0]
+
+    def p_definition_as(self, t):
+        r'''definition : IDENTIFIER AS expression
+        '''
+        #t[0]=''
+        if DEBUG: print 'reducing "IDENTIFIER AS expression" to "definition"', t[0]
+
+    def p_literal_constant(self, t):
+        r'''literal : CONSTANT
+        '''
+        t[0] = Constant(self.metadata, self.symbols, t[1])
+        if DEBUG: print 'reducing "CONSTANT" to "literal"', t[0]
+
+    def p_literal_element(self, t):
+        r'''literal : collection CBRACKET_L element CBRACKET_R
+        '''
+        raise NotImplementedError('collection set')
+        if DEBUG: print 'reducing "collection CBRACKET_L element CBRACKET_R" to "literal"', t[0]
+
+    def p_element_null(self, t):
+        r'''element :
+        '''
+        t[0] = None
+        if DEBUG: print 'reducing "" to "element"', t[0]
+
+    def p_element_expression(self, t):
+        r'''element : expression
+        '''
+        t[0] = t[1]
+        if DEBUG: print 'reducing "expression" to "element"', t[0]
+
+# Why this raise a shift/reduce conflict
+#    def p_element_comma(self, t):
+#        r'''element : element COMMA element
+#        '''
+#        raise NotImplementedError('element list')
+#        if DEBUG: print 'reducing "element COMMA element" to "element"', t[0]
+
+    def p_element_ellipsis(self, t):
+        r'''element : expression ELLIPSIS expression
+        '''
+        raise NotImplementedError('range')
+        if DEBUG: print 'reducing "expression ELLIPSIS expression" to "element"', t[0]
+
+    def p_path_identifier(self, t):
+        r'''path : IDENTIFIER
+        '''
+        t[0] = Identifier(self.metadata, self.symbols, t[1])
+        if DEBUG: print 'reducing "IDENTIFIER" to "path"', t[0]
+
+    def p_path_method(self, t):
+        r'''path : IDENTIFIER DOT method
+        '''
+        t[0] = Property(self.metadata, self.symbols, Identifier(self.metadata, self.symbols, t[1]), t[3])
+        if DEBUG: print 'reducing "IDENTIFIER DOT method" to "path"', t[0]
+
+    def p_method_identifier(self, t):
+        r'''method : IDENTIFIER
+        '''
+        t[0] = Identifier(self.metadata, self.symbols, t[1])
+        if DEBUG: print 'reducing "IDENTIFIER" to "method"', t[0]
+
+    def p_method_arguments(self, t):
+        r'''method : IDENTIFIER BRACKET_L argument_list BRACKET_R
+        '''
+        raise NotImplementedError('function call')
+        if DEBUG: print 'reducing "IDENTIFIER BRACKET_L argument_list BRACKET_R" to "method"', t[0]
+
+    def p_argument_list_null(self, t):
+        r'''argument_list :
+        '''
+        t[0] = None
+        if DEBUG: print 'reducing "" to "argument_list"', t[0]
+
+    def p_argument_list_expression(self, t):
+        r'''argument_list : expression
+        '''
+        t[0] = t[1]
+        if DEBUG: print 'reducing "expression" to "argument_list"', t[0]
+
+    def p_argument_list_set(self, t):
+        r'''argument_list : expression COMMA argument_list
+        '''
+        t[0]=''
+        if DEBUG: print 'reducing "expression COMMA argument_list" to "argument_list"', t[0]
+
+    def p_call(self, t):
+        r'''call : IDENTIFIER BRACKET_L argument_list BRACKET_R
+        '''
+        raise NotImplementedError('function call')
+        if DEBUG: print 'reducing "IDENTIFIER BRACKET_L argument_list BRACKET_R" to "call"', t[0]
+
+#these are here, to keep lexer and parser instantiation to a minimum possible
+#level because they are quite expensive operations
+#parsers must be thread safe on the other hand!
+LEXER = lex.lex(object=Lexer(), debug=0)
+#PARSERS = local()
+
+def parse(str, metadata):
+    lexer = LEXER.clone()
+
+    #global PARSERS
+    #try:
+    #    parser = PARSERS.parser
+    #
+    #    try:
+    #        parser.restart()
+    #    except AttributeError:
+    #        pass
+    #
+    #except AttributeError:
+    #    parser = yacc.yacc(module = Parser(metadata))
+    #    PARSERS.parser = parser
+
+    try:
+        parser = yacc.yacc(module = Parser(metadata))
+
+        retval = parser.parse(str, lexer = lexer)
+    except Exception, e:
+        if DEBUG: print e
+        raise
+    return retval
+
+class QueryParser(object):
+    implements(IQueryParser)
+    adapts(basestring)
+
+    def __init__(self, context):
+        self.context = context
+        #self.db = db
+
+    def __call__(self, metadata):
+        strg = self.context
+        tree = parse(strg, metadata)
+        return Head(tree)
+        #return parse(strg, None)
\ No newline at end of file

Modified: Sandbox/adamg/ocql/trunk/src/ocql/rewriter/algebra.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/rewriter/algebra.py	2008-08-08 09:04:59 UTC (rev 89533)
+++ Sandbox/adamg/ocql/trunk/src/ocql/rewriter/algebra.py	2008-08-08 09:13:02 UTC (rev 89534)
@@ -16,6 +16,7 @@
 from ocql.interfaces import IAlgebraObjectHead
 from ocql.rewriter.interfaces import *
 from zope.location import Location, locate
+from zope.location.interfaces import ILocation
 
 class Head(Location):
     implements(IAlgebraObjectHead)
@@ -33,8 +34,16 @@
 
 class BaseAlgebra(Location):
     implements(IAlgebraObject)
-    children = []
 
+    def __init__(self):
+        self.children = []
+
+    def setProp(self, name, value):
+        setattr(self, name, value)
+        if ILocation.providedBy(value):
+            locate(value, self, name)
+            self.children.append(value)
+
     def walk(self):
         yield self
         for child in self.children:
@@ -45,7 +54,8 @@
     implements(IEmpty)
 
     def __init__(self, klass):
-        self.klass = klass
+        BaseAlgebra.__init__(self)
+        self.setProp('klass', klass)
 
     def __repr__(self):
         return 'Empty(%s)'%(self.klass)
@@ -54,110 +64,95 @@
     implements(ISingle)
 
     def __init__(self, klass, expr):
-        self.klass = klass
-        self.expr = expr
-        locate(expr, self, 'expr')
-        self.children.extend([klass, expr])
+        BaseAlgebra.__init__(self)
+        self.setProp('klass', klass)
+        self.setProp('expr', expr)
 
     def __repr__(self):
-        return 'Single(%s,%s)'%(self.klass, self.expr)
+        return 'Single(%s, %s)'%(self.klass, self.expr)
 
 class Union(BaseAlgebra):
     implements(IUnion)
 
     def __init__(self, klass, coll1, coll2):
-        self.klass=klass
-        self.coll1=coll1
-        self.coll2=coll2
-        locate(coll1, self, 'coll1')
-        locate(coll2, self, 'coll2')
-        self.children.extend([coll1, coll2])
+        BaseAlgebra.__init__(self)
+        self.setProp('klass', klass)
+        self.setProp('coll1', coll1)
+        self.setProp('coll2', coll2)
 
     def __repr__(self):
-        return 'Union(%s,%s,%s)'%(self.klass, self.coll1, self.coll2)
+        return 'Union(%s, %s, %s)' % (self.klass, self.coll1, self.coll2)
 
 class Differ(BaseAlgebra):
     implements(IDiffer)
 
     def __init__(self, klass, coll1, coll2):
-        self.klass = klass
-        self.coll1 = coll1
-        self.coll2 = coll2
-        locate(coll1, self, 'coll1')
-        locate(coll2, self, 'coll2')
-        self.children.extend([coll1, coll2])
+        BaseAlgebra.__init__(self)
+        self.setProp('klass', klass)
+        self.setProp('coll1', coll1)
+        self.setProp('coll2', coll2)
 
     def __repr__(self):
-        return 'Differ(%s,%s,%s)'%(self.klass, self.coll1, self.coll2)
+        return 'Differ(%s, %s, %s)' % (self.klass, self.coll1, self.coll2)
 
 class Iter(BaseAlgebra):
     implements(IIter)
 
     def __init__(self, klass, func, coll):
-        self.klass = klass
-        self.func = func
-        self.coll = coll
-        locate(func, self, 'func')
-        locate(coll, self, 'coll')
-        self.children.extend([func,coll])
+        BaseAlgebra.__init__(self)
+        self.setProp('klass', klass)
+        self.setProp('func', func)
+        self.setProp('coll', coll)
 
     def __repr__(self):
-        return "Iter(%s,%s,%s)"%(self.klass, self.func, self.coll)
+        return "Iter(%s, %s, %s)"%(self.klass, self.func, self.coll)
 
 class Select(BaseAlgebra):
     implements(ISelect)
 
     def __init__(self, klass, func, coll):
-        self.klass = klass
-        self.func = func
-        self.coll = coll
-        locate(func, self, 'func')
-        locate(coll, self, 'coll')
-        self.children.extend([func,coll])
+        BaseAlgebra.__init__(self)
+        self.setProp('klass', klass)
+        self.setProp('func', func)
+        self.setProp('coll', coll)
 
     def __repr__(self):
-        return "Select(%s,%s,%s)"%(self.klass, self.func, self.coll)
+        return "Select(%s, %s, %s)"%(self.klass, self.func, self.coll)
 
 class Reduce(BaseAlgebra):
     implements(IReduce)
 
     def __init__(self, klass, expr, func, aggreg, coll):
-        self.klass = klass
-        self.expr = expr
-        self.func = func
-        self.aggreg = aggreg
-        self.coll = coll
-        locate(expr, self, 'expr')
-        locate(func, self, 'func')
-        locate(aggreg, self, 'aggreg')
-        locate(coll, self, 'coll')
-        self.children.extend([expr, func, aggreg, coll])
+        BaseAlgebra.__init__(self)
+        self.setProp('klass', klass)
+        self.setProp('expr', expr)
+        self.setProp('func', func)
+        self.setProp('aggreg', aggreg)
+        self.setProp('coll', coll)
 
     def __repr__(self):
-        return "Reduce(%s,%s,%s,%s,%s)"%(self.klass, self.expr, self.func, self.aggreg, self.coll)
+        return "Reduce(%s, %s, %s, %s, %s)"%(self.klass, self.expr, self.func, self.aggreg, self.coll)
 
 #class Equal:
 #    def __init__(self, klass, coll1, coll2):
-#        self.klass = klass
-#        self.coll1 = coll1
-#        self.coll2 = coll2
+#        self.setProp('klass', klass)
+#        self.setProp('coll1', coll1)
+#        self.setProp('coll2', coll2)
 #
 #    def compile(self):
 #        if self.klass == set:
-#            return 'set(filter(%s,%s))' % (self.coll1.compile(),self.coll1.compile())
+#            return 'set(filter(%s, %s))' % (self.coll1.compile(),self.coll1.compile())
 #        if self.klass == list:
-#            return 'filter(%s,%s)' % (self.coll1.compile(),self.coll2.compile())
+#            return 'filter(%s, %s)' % (self.coll1.compile(),self.coll2.compile())
 #
 class Range(BaseAlgebra):
     implements(IRange)
 
     def __init__(self, klass, start, end):
-        self.klass = klass
-        self.start = start
-        self.end = end
-        locate(start, self, 'start')
-        locate(end, self, 'end')
-        self.children.extend([start, end])
+        BaseAlgebra.__init__(self)
+        self.setProp('klass', klass)
+        self.setProp('start', start)
+        self.setProp('end', end)
 
 #class Index
 
@@ -165,18 +160,33 @@
     implements(IMake)
 
     def __init__(self, coll1, coll2, expr):
-        self.expr = expr
-        self.coll1 = coll1
-        self.coll2 = coll2
-        locate(expr, self, 'expr')
-#        locate(coll1, self, 'coll1')
-#        locate(coll2, self, 'coll2')
-        self.children.append(expr)
+        BaseAlgebra.__init__(self)
+        self.setProp('expr', expr)
+        self.setProp('coll1', coll1)
+        self.setProp('coll2', coll2)
 
     def __repr__(self):
-        return "Make(%s,%s,%s)" %(self.coll1, self.coll2, self.expr)
+        return "Make(%s, %s, %s)" %(self.coll1, self.coll2, self.expr)
 
 
+class MakeFromIndex(BaseAlgebra):
+    
+    implements(IMakeFromIndex)
+
+    def __init__(self, coll1, coll2, expr1, expr2, operator, value):
+        BaseAlgebra.__init__(self)
+        self.setProp('expr1', expr1)
+        self.setProp('expr2', expr2)
+        self.setProp('coll1', coll1)
+        self.setProp('coll2', coll2)
+        self.setProp('operator', operator)
+        self.setProp('value', value)
+
+    def __repr__(self):
+        return "MakeFromIndex(%s, %s, %s, %s, %s)" % (
+            self.coll1, self.coll2, self.expr1, self.expr2, self.value)
+
+
 #class And:
 #class Being:
 
@@ -184,16 +194,13 @@
     implements(IIf)
 
     def __init__(self, cond, expr1, expr2):
-        self.cond = cond
-        self.expr1 = expr1
-        self.expr2 = expr2
-        locate(cond, self, 'cond')
-        locate(expr1, self, 'expr1')
-        locate(expr2, self, 'expr2')
-        self.children.extend([cond, expr1, expr2])
+        BaseAlgebra.__init__(self)
+        self.setProp('cond', cond)
+        self.setProp('expr1', expr1)
+        self.setProp('expr2', expr2)
 
     def __repr__(self):
-        return "If(%s,%s,%s)" % (self.cond, self.expr1, self.expr2)
+        return "If(%s, %s, %s)" % (self.cond, self.expr1, self.expr2)
 
 #
 #
@@ -202,10 +209,9 @@
     implements(ILambda)
 
     def __init__(self, var, expr):
-        self.var = var
-        self.expr = expr
-        locate(expr, self, 'expr')
-        self.children.append(expr)
+        BaseAlgebra.__init__(self)
+        self.setProp('var', var)
+        self.setProp('expr', expr)
 
     def __repr__(self):
         return "Lambda %s: %s" %(self.var, self.expr)
@@ -214,6 +220,7 @@
     implements(IConstant)
 
     def __init__(self, value):
+        BaseAlgebra.__init__(self)
         self.value = value
 
     def __repr__(self):
@@ -223,6 +230,7 @@
     implements(IIdentifier)
 
     def __init__(self, name):
+        BaseAlgebra.__init__(self)
         self.name=name
 
     def __repr__(self):
@@ -232,12 +240,10 @@
     implements(IBinary)
 
     def __init__(self, left, op, right):
-        self.left = left
-        self.op = op
-        self.right = right
-        locate(left, self, 'left')
-        locate(right, self, 'right')
-        self.children.extend([left, right])
+        BaseAlgebra.__init__(self)
+        self.setProp('left', left)
+        self.setProp('op', op)
+        self.setProp('right', right)
 
     def __repr__(self):
         return "%s%s%s" % (self.left, self.op.op, self.right)
@@ -246,6 +252,7 @@
     implements(IOperator)
 
     def __init__(self, op):
+        BaseAlgebra.__init__(self)
         self.op = op
 
     def __repr__(self):

Modified: Sandbox/adamg/ocql/trunk/src/ocql/rewriter/interfaces.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/rewriter/interfaces.py	2008-08-08 09:04:59 UTC (rev 89533)
+++ Sandbox/adamg/ocql/trunk/src/ocql/rewriter/interfaces.py	2008-08-08 09:13:02 UTC (rev 89534)
@@ -79,6 +79,17 @@
     coll1 = Attribute('first collection')
     coll2 = Attribute('second collection')
 
+class IMakeFromIndex(IAlgebraObject):
+    """Objects providing this interface represent the
+    MakeFromIndex Algebra object
+    """
+    expr1 = Attribute('expression1')
+    expr2 = Attribute('expression2')
+    coll1 = Attribute('first collection')
+    coll2 = Attribute('second collection')
+    operator = Attribute('operator')
+    value = Attribute('boundary value of the query')
+
 class IIf(IAlgebraObject):
     """Objects providing this interface represent the
     If Algebra object

Modified: Sandbox/adamg/ocql/trunk/src/ocql/rewriter/rewriter.txt
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/rewriter/rewriter.txt	2008-08-08 09:04:59 UTC (rev 89533)
+++ Sandbox/adamg/ocql/trunk/src/ocql/rewriter/rewriter.txt	2008-08-08 09:13:02 UTC (rev 89534)
@@ -20,43 +20,43 @@
     >>> opt = QueryOptimizer(qo)()
     >>> alg = Rewriter(opt)()
     >>> print str(alg)
-    Single(<type 'set'>,`1`)
+    Single(<type 'set'>, `1`)
 
     >>> qo = QueryParser("list [ | 1 ]")(TestMetadata())
     >>> opt = QueryOptimizer(qo)()
     >>> alg = Rewriter(opt)()
     >>> print str(alg)
-    Single(<type 'list'>,`1`)
+    Single(<type 'list'>, `1`)
 
     >>> qo = QueryParser("set [ | 1 ] union set [|2]")(TestMetadata())
     >>> opt = QueryOptimizer(qo)()
     >>> alg = Rewriter(opt)()
     >>> print str(alg)
-    Union(<type 'set'>,Single(<type 'set'>,`1`),Single(<type 'set'>,`2`))
+    Union(<type 'set'>, Single(<type 'set'>, `1`), Single(<type 'set'>, `2`))
 
     >>> qo = QueryParser("list [ | 1 ] union list [|2]")(TestMetadata())
     >>> opt = QueryOptimizer(qo)()
     >>> alg = Rewriter(opt)()
     >>> print str(alg)
-    Union(<type 'list'>,Single(<type 'list'>,`1`),Single(<type 'list'>,`2`))
+    Union(<type 'list'>, Single(<type 'list'>, `1`), Single(<type 'list'>, `2`))
 
     >>> qo = QueryParser("set [ | 1 ] differ set [|2]")(TestMetadata())
     >>> opt = QueryOptimizer(qo)()
     >>> alg = Rewriter(opt)()
     >>> print str(alg)
-    Differ(<type 'set'>,Single(<type 'set'>,`1`),Single(<type 'set'>,`2`))
+    Differ(<type 'set'>, Single(<type 'set'>, `1`), Single(<type 'set'>, `2`))
 
     >>> qo = QueryParser("list [ | 1 ] differ list [|2]")(TestMetadata())
     >>> opt = QueryOptimizer(qo)()
     >>> alg = Rewriter(opt)()
     >>> print str(alg)
-    Differ(<type 'list'>,Single(<type 'list'>,`1`),Single(<type 'list'>,`2`))
+    Differ(<type 'list'>, Single(<type 'list'>, `1`), Single(<type 'list'>, `2`))
 
     >>> qo = QueryParser("set [ i in ICourse | i ]")(TestMetadata())
     >>> opt = QueryOptimizer(qo)()
     >>> alg = Rewriter(opt)()
     >>> print str(alg)
-    Iter(<type 'set'>,Lambda i: Single(<type 'set'>,i),Make(<type 'set'>,<type 'set'>,ICourse))
+    Iter(<type 'set'>, Lambda i: Single(<type 'set'>, i), Make(<type 'set'>, <type 'set'>, ICourse))
 
 #    >>> qo = QueryParser("list [ i in ICourse | i ]")(TestMetadata())
 #    >>> opt = QueryOptimizer(qo)()
@@ -64,9 +64,16 @@
 #    >>> print str(alg)
 #    Iter(<type 'list'>,Lambda i: Single(<type 'list'>,i),Make(<type 'list'>,<type 'list'>,ICourse))
 
+    #>>> qo = QueryParser("set [ c in ICourse; c.credits>3 | c.code ]")(TestMetadata())
+    #>>> opt = QueryOptimizer(qo)()
+    #>>> alg = Rewriter(opt)()
+    #>>> print str(alg)
+    #Iter(<type 'set'>, Lambda c: If(c.credits>`3`, Single(<type 'set'>, c.code), Empty(<type 'set'>)), Make(<type 'set'>, <type 'set'>, ICourse))
+
+
     #bag not implemented
     #>>> qo = QueryParser("size set [ i in ICourse | i ]")(TestMetadata())
     #>>> opt = QueryOptimizer(qo)()
     #>>> alg = Rewriter(opt)()
     #>>> print str(alg)
-    #Iter(<type 'set'>,Lambda i: Single(<type 'set'>,i),Make(<type 'set'>,<type 'set'>,ICourse))
\ No newline at end of file
+    #Iter(<type 'set'>, Lambda i: Single(<type 'set'>, i), Make(<type 'set'>, <type 'set'>, ICourse))

Modified: Sandbox/adamg/ocql/trunk/src/ocql/testing/database.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/testing/database.py	2008-08-08 09:04:59 UTC (rev 89533)
+++ Sandbox/adamg/ocql/trunk/src/ocql/testing/database.py	2008-08-08 09:13:02 UTC (rev 89534)
@@ -130,9 +130,4 @@
         return x
 
     def get_class(self, name):
-        return self.classes[name]
-
-    #def get_collection_type(self, name):
-    #    klass = self.get_class(name)
-    #    rv = klass.get_collection_type()
-    #    return rv
\ No newline at end of file
+        return self.classes[name]
\ No newline at end of file

Modified: Sandbox/adamg/ocql/trunk/src/ocql/testing/sample/interfaces.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/testing/sample/interfaces.py	2008-08-08 09:04:59 UTC (rev 89533)
+++ Sandbox/adamg/ocql/trunk/src/ocql/testing/sample/interfaces.py	2008-08-08 09:13:02 UTC (rev 89534)
@@ -36,8 +36,8 @@
     """A Student object"""
 
     name = TextLine(title=u"Student Name")
+    country = Attribute('student country')
 
-
 class IMentor(Interface):
     """A Mentor object"""
 
@@ -54,13 +54,13 @@
     containers(".IGsoc")
 
 
+#class IProjectRelation(Interface):
+#    mentor = Attribute('assigned mentor for the project')
+#    project = Attribute('mentoring project')
+#
+#
+
 class IOrganizationContainer(IContainer):
     """Organization is also a container for projects, students and mentors"""
 
-    contains(".IProject", ".IStudent", ".IMentor")
-    
-#class IProjectRelation(Interface):
-#    mentor = Attribute('assigned mentor for the project')
-#    project = Attribute('mentoring project')
-#    
-#    
\ No newline at end of file
+    contains(".IProject", ".IStudent", ".IMentor")
\ No newline at end of file

Modified: Sandbox/adamg/ocql/trunk/src/ocql/testing/sample/project.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/testing/sample/project.py	2008-08-08 09:04:59 UTC (rev 89533)
+++ Sandbox/adamg/ocql/trunk/src/ocql/testing/sample/project.py	2008-08-08 09:13:02 UTC (rev 89534)
@@ -5,6 +5,13 @@
 
 from ocql.testing.sample.interfaces import IProject
 
+#class ProjectRelation(object):
+#    implements(IProjectRelation)
+#
+#    def __init__(self, mentor, project):
+#        self.mentor = mentor
+#        self.project = project
+
 class Project(persistent.Persistent):
     """A simple implementation of a Project .
 
@@ -31,12 +38,4 @@
     name = u''
 
     def __repr__(self):
-        return "%s <%s>" % (self.__class__.__name__, self.name)
-
-
-#class ProjectRelation(object):
-#    implements(IProjectRelation)
-#    
-#    def __init__(self, mentor, project):
-#        self.mentor = mentor
-#        self.project = project
+        return "%s <%s>" % (self.__class__.__name__, self.name)
\ No newline at end of file

Modified: Sandbox/adamg/ocql/trunk/src/ocql/testing/sample/student.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/testing/sample/student.py	2008-08-08 09:04:59 UTC (rev 89533)
+++ Sandbox/adamg/ocql/trunk/src/ocql/testing/sample/student.py	2008-08-08 09:13:02 UTC (rev 89534)
@@ -1,6 +1,6 @@
 # -*- coding: UTF-8 -*-
 from zope.interface import implements
-from zope.interface import Interface
+from zope.interface import Interface, Attribute
 import persistent
 
 from ocql.testing.sample.interfaces import IStudent
@@ -26,6 +26,7 @@
     implements(IStudent)
 
     name = u''
+    country = None
 
     def __repr__(self):
         return "%s <%s>" % (self.__class__.__name__, self.name)

Modified: Sandbox/adamg/ocql/trunk/src/ocql/testing/stubs.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/testing/stubs.py	2008-08-08 09:04:59 UTC (rev 89533)
+++ Sandbox/adamg/ocql/trunk/src/ocql/testing/stubs.py	2008-08-08 09:13:02 UTC (rev 89534)
@@ -77,7 +77,7 @@
         self.context = context
         #self.db = db
 
-    def __call__(self):
+    def __call__(self, metadata):
         return AlgebraOptimized()
 
 class AlgebraCompiler(object):

Modified: Sandbox/adamg/ocql/trunk/src/ocql/testing/utils.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/testing/utils.py	2008-08-08 09:04:59 UTC (rev 89533)
+++ Sandbox/adamg/ocql/trunk/src/ocql/testing/utils.py	2008-08-08 09:13:02 UTC (rev 89534)
@@ -11,6 +11,7 @@
 from zope.app.catalog.catalog import Catalog
 from zope.app.catalog.interfaces import ICatalog
 from zope.app.catalog.field import FieldIndex
+from zope.app.catalog.attribute import AttributeIndex
 from ocql.database.index import AllIndex
 
 from zope.app.intid import IntIds
@@ -27,10 +28,10 @@
 from ocql.testing.sample.project import Project
 from ocql.testing.sample.student import Student
 from ocql.testing.sample.organization import Organization
-        
-import zc.relation.catalog
-import zc.relation.interfaces
-import zc.relation.queryfactory
+
+#import zc.relation.catalog
+#import zc.relation.interfaces
+#import zc.relation.queryfactory
 import BTrees
 
 #_obj = {}
@@ -70,6 +71,7 @@
     cat['proj_descr'] = FieldIndex('description', IProject)
 
     cat['student_name'] = FieldIndex('name', IStudent)
+    cat['student_country'] = FieldIndex('country', IStudent)
 
     cat['mentor_name'] = FieldIndex('name', IMentor)
 
@@ -91,16 +93,19 @@
 
     s1 = Student()
     s1.name = u"Charith"
+    s1.country = "Sri Lanka"
     id = intids.register(s1)
     cat.index_doc(id, s1)
 
     s2 = Student()
     s2.name = u"Jane"
+    s2.country = "USA"
     id = intids.register(s2)
     cat.index_doc(id, s2)
 
     s3 = Student()
     s3.name = u"Ann"
+    s3.country = "Hungary"
     id = intids.register(s3)
     cat.index_doc(id, s3)
 
@@ -108,7 +113,7 @@
     o1.name = u"Zope.org"
     id = intids.register(o1)
     cat.index_doc(id, o1)
-    
+
 #    cat2 = zc.relation.catalog.Catalog(dumpRelation, loadRelation)
 #    cat2.addValueIndex(IProjectRelation['project'], dumpObj, loadObj, btree=BTrees.family32.OO)
 #    cat2.addValueIndex(IProjectRelation['mentor'], dumpObj, loadObj, btree=BTrees.family32.OO)
@@ -135,12 +140,4 @@
 
     for r in results:
         obj = intids.getObject(r)
-        print obj
-        
-#    rel_mentor = cat.apply({'all_mentors':(1,1)})
-#    
-#    for r in rel_mentor:
-#        obj = intids.getObject(r)     
-#        for p in cat2.findValueTokens('project',query(mentor=obj)):
-#            print p.name
-#    
\ No newline at end of file
+        print obj
\ No newline at end of file

Copied: Sandbox/adamg/ocql/trunk/src/ocql/testing/utils_opt.py (from rev 89533, Sandbox/adamg/ocql/branches/optimize-with-index/src/ocql/testing/utils_opt.py)
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/testing/utils_opt.py	                        (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/testing/utils_opt.py	2008-08-08 09:13:02 UTC (rev 89534)
@@ -0,0 +1,123 @@
+# -*- coding: UTF-8 -*-
+
+"""Utilities for testing support
+
+$Id$
+"""
+
+from zope import interface, component
+from zope.component.interface import provideInterface
+
+from zope.schema import Text, TextLine, Int
+
+from zope.app.catalog.catalog import Catalog
+from zope.app.catalog.interfaces import ICatalog
+from zope.app.catalog.field import FieldIndex
+from ocql.database.index import AllIndex
+
+from zope.app.intid import IntIds
+from zope.app.intid.interfaces import IIntIds
+
+from zope.app.keyreference.testing import SimpleKeyReference
+
+from ocql.testing.sample.interfaces import IOrganization
+from ocql.testing.sample.interfaces import IProject
+from ocql.testing.sample.interfaces import IStudent
+from ocql.testing.sample.interfaces import IMentor
+
+from ocql.testing.sample.mentor import Mentor
+from ocql.testing.sample.project import Project
+from ocql.testing.sample.student import Student
+from ocql.testing.sample.organization import Organization
+
+#import zc.relation.catalog
+#import zc.relation.interfaces
+#import zc.relation.queryfactory
+import BTrees
+
+
+class IOptimizedClass(interface.Interface):
+    name = TextLine(title=u"Name")
+    value = Int(title=u"value")
+
+class IUnOptimizedClass(interface.Interface):
+    name = TextLine(title=u"Name")
+    value = Int(title=u"value")
+
+class IHalfOptimizedClass(interface.Interface):
+    name = TextLine(title=u"Name")
+    valueOpt = Int(title=u"value")
+    valueNoOpt = Int(title=u"value")
+
+class OptimizedClass(object):
+    interface.implements(IOptimizedClass)
+
+    name = u''
+    value = 0
+
+    def __repr__(self):
+        return "Opt: %s" % self.name
+
+class UnOptimizedClass(object):
+    interface.implements(IUnOptimizedClass)
+
+    name = u''
+    value = 0
+
+    def __repr__(self):
+        return "UnOpt: %s" % self.name
+
+class HalfOptimizedClass(object):
+    interface.implements(IHalfOptimizedClass)
+
+    name = u''
+    valueOpt = 0
+    valueNoOpt = 0
+
+    def __repr__(self):
+        return "HalfOpt: %s" % self.name
+
+def setupInterfaces(test):
+    provideInterface('', IOptimizedClass)
+    provideInterface('', IUnOptimizedClass)
+    provideInterface('', IHalfOptimizedClass)
+
+def setupCatalog(test, optCount=10, unoptCount=10, halfCount=10):
+    intids = IntIds()
+    component.provideUtility(intids, IIntIds)
+    component.provideAdapter(SimpleKeyReference)
+    cat = Catalog()
+
+    cat['opt_name'] = FieldIndex('name', IOptimizedClass)
+    cat['opt_value'] = FieldIndex('value', IOptimizedClass)
+
+    cat['half_name'] = FieldIndex('name', IHalfOptimizedClass)
+    cat['half_valueOpt'] = FieldIndex('value', IHalfOptimizedClass)
+
+    cat['all_opt'] = AllIndex(IOptimizedClass)
+    cat['all_unopt'] = AllIndex(IUnOptimizedClass)
+    cat['all_half'] = AllIndex(IHalfOptimizedClass)
+
+    for i in range(optCount):
+        o = OptimizedClass()
+        o.value = i
+        o.name = unicode(i)
+        id = intids.register(o)
+        cat.index_doc(id, o)
+
+    for i in range(unoptCount):
+        o = UnOptimizedClass()
+        o.value = i
+        o.name = unicode(i)
+        id = intids.register(o)
+        cat.index_doc(id, o)
+
+    for i in range(halfCount):
+        o = HalfOptimizedClass()
+        o.valueOpt = i
+        o.valueNoOpt = i
+        o.name = unicode(i)
+        id = intids.register(o)
+        cat.index_doc(id, o)
+
+    component.provideUtility(cat, ICatalog, name='foo-catalog')

Modified: Sandbox/adamg/ocql/trunk/src/ocql/tests/run.txt
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/tests/run.txt	2008-08-08 09:04:59 UTC (rev 89533)
+++ Sandbox/adamg/ocql/trunk/src/ocql/tests/run.txt	2008-08-08 09:13:02 UTC (rev 89534)
@@ -46,8 +46,8 @@
     RunnableQuery: set.union(set([1]), set([2]))
 
     >>> result = run.execute()
-    >>> result
-    set([1, 2])
+    >>> sorted(list(result))
+    [1, 2]
 
     >>> type(result)
     <type 'set'>
@@ -57,11 +57,11 @@
     >>> engine = OCQLEngine()
     >>> run = engine.compile("set [ i in ICourse | i ]")
     >>> run
-    RunnableQuery: reduce(set.union, map(lambda i: set([i]),set(metadata.getAll("ICourse"))), set())
+    RunnableQuery: reduce(set.union, map(lambda i: set([i]), set(metadata.getAll("ICourse"))), set())
 
     >>> result = run.execute()
-    >>> result
-    set([Course <C1>, Course <C2>, Course <C3>])
+    >>> sorted(list(result), key=lambda i: i.code)
+    [Course <C1>, Course <C2>, Course <C3>]
 
     >>> type(result)
     <type 'set'>
@@ -71,15 +71,19 @@
     >>> engine = OCQLEngine()
     >>> run = engine.compile("set [ c in ICourse | c.code ]")
     >>> run
-    RunnableQuery: reduce(set.union, map(lambda c: set([c.code]),set(metadata.getAll("ICourse"))), set())
+    RunnableQuery: reduce(set.union, map(lambda c: set([c.code]), set(metadata.getAll("ICourse"))), set())
 
     >>> result = run.execute()
-    >>> result
-    set(['C3', 'C2', 'C1'])
+    >>> type(result)
+    <type 'set'>
+    >>> len(result)
+    3
+    >>> sorted(list(result))
+    ['C1', 'C2', 'C3']
 
     >>> type(result)
     <type 'set'>
 
     >>> run = run.reanalyze()
-    >>> run.execute()
-    set(['C3', 'C2', 'C1'])
\ No newline at end of file
+    >>> sorted(list(run.execute()))
+    ['C1', 'C2', 'C3']
\ No newline at end of file

Modified: Sandbox/adamg/ocql/trunk/src/ocql/tests/test_old.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/tests/test_old.py	2008-08-08 09:04:59 UTC (rev 89533)
+++ Sandbox/adamg/ocql/trunk/src/ocql/tests/test_old.py	2008-08-08 09:13:02 UTC (rev 89534)
@@ -166,6 +166,9 @@
                     Constant(metadata, symbols,'3')),
             ] ,Identifier(metadata, symbols, 'c.code') ))
 
+        #from pub.dbgpclient import brk; brk('172.16.144.39')
+
+
         self.doit(query, qo, set([]))
 
 

Modified: Sandbox/adamg/ocql/trunk/src/ocql/tests/test_zope.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/tests/test_zope.py	2008-08-08 09:04:59 UTC (rev 89533)
+++ Sandbox/adamg/ocql/trunk/src/ocql/tests/test_zope.py	2008-08-08 09:13:02 UTC (rev 89534)
@@ -147,6 +147,30 @@
         self.doit(query, qo, set(["Save the world"]))
 
 
+        symbols = SymbolContainer()
+        #
+        # Filtering --one result using optimization
+        #
+        # set [ c in IStudent , c.country="USA" | c.name]
+        #
+        query = "[c in IStudent , c.country=USA | c.name]"
+        qo = Head(Query(
+                   metadata, symbols,
+                   set,
+                   [
+                        In(
+                           metadata, symbols,
+                           Identifier(metadata,symbols,'c'),
+                           Identifier(metadata,symbols, 'IStudent')),
+                        Eq(
+                           metadata,symbols,
+                           Identifier(metadata, symbols, 'c.country'),
+                           Identifier(metadata, symbols, '"USA"'))
+                   ], Identifier(metadata, symbols, 'c.name')))
+
+        self.doit(query, qo, set([metadata.getFromIndex('IStudent', 'country','==', 'USA')[0].name]))
+
+
 def test_suite():
     flags =  doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS
     return unittest.TestSuite((



More information about the Checkins mailing list