[Checkins] SVN: Sandbox/adamg/ocql/trunk/s moving code from old repo
Adam Groszer
agroszer at gmail.com
Sun Jun 15 10:35:59 EDT 2008
Log message for revision 87410:
moving code from old repo
made a lot of refactoring... still a lot of TODOs
paving the way for Charith
Changed:
U Sandbox/adamg/ocql/trunk/setup.py
A Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/aoptimizer.py
A Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/aoptimizer.txt
A Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/tests.py
A Sandbox/adamg/ocql/trunk/src/ocql/compiler/compiler.py
A Sandbox/adamg/ocql/trunk/src/ocql/compiler/compiler.txt
A Sandbox/adamg/ocql/trunk/src/ocql/compiler/runnablequery.py
A Sandbox/adamg/ocql/trunk/src/ocql/compiler/tests.py
A Sandbox/adamg/ocql/trunk/src/ocql/database/
A Sandbox/adamg/ocql/trunk/src/ocql/database/__init__.py
A Sandbox/adamg/ocql/trunk/src/ocql/database/metadata.py
U Sandbox/adamg/ocql/trunk/src/ocql/engine.py
A Sandbox/adamg/ocql/trunk/src/ocql/parser/parser.txt
A Sandbox/adamg/ocql/trunk/src/ocql/parser/queryparser.py
A Sandbox/adamg/ocql/trunk/src/ocql/parser/tests.py
A Sandbox/adamg/ocql/trunk/src/ocql/qoptimizer/qoptimizer.py
A Sandbox/adamg/ocql/trunk/src/ocql/qoptimizer/qoptimizer.txt
A Sandbox/adamg/ocql/trunk/src/ocql/qoptimizer/tests.py
A Sandbox/adamg/ocql/trunk/src/ocql/queryobject/
A Sandbox/adamg/ocql/trunk/src/ocql/queryobject/__init__.py
A Sandbox/adamg/ocql/trunk/src/ocql/queryobject/queryobject.py
A Sandbox/adamg/ocql/trunk/src/ocql/rewriter/algebra.py
A Sandbox/adamg/ocql/trunk/src/ocql/rewriter/rewriter.py
A Sandbox/adamg/ocql/trunk/src/ocql/rewriter/rewriter.txt
A Sandbox/adamg/ocql/trunk/src/ocql/rewriter/tests.py
A Sandbox/adamg/ocql/trunk/src/ocql/testing/database.py
U Sandbox/adamg/ocql/trunk/src/ocql/testing/stubs.py
A Sandbox/adamg/ocql/trunk/src/ocql/tests/run.txt
U Sandbox/adamg/ocql/trunk/src/ocql/tests/test_skeleton.py
-=-
Modified: Sandbox/adamg/ocql/trunk/setup.py
===================================================================
--- Sandbox/adamg/ocql/trunk/setup.py 2008-06-15 12:38:04 UTC (rev 87409)
+++ Sandbox/adamg/ocql/trunk/setup.py 2008-06-15 14:35:58 UTC (rev 87410)
@@ -27,9 +27,10 @@
url = '',
packages = find_packages('src'),
package_dir = {'':'src'},
- namespace_packages = ['ocql'],
+ namespace_packages = [],
extras_require = dict(
test = [
+ 'zope.testing',
],
),
install_requires = [
Added: Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/aoptimizer.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/aoptimizer.py (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/aoptimizer.py 2008-06-15 14:35:58 UTC (rev 87410)
@@ -0,0 +1,35 @@
+# -*- coding: UTF-8 -*-
+
+""" Optimizing will be done later,
+at the moment this is just a stub returning it's input
+
+$Id$
+"""
+
+from zope.component import adapts
+from zope.interface import implements
+from zope.security.proxy import removeSecurityProxy
+from zope.interface import directlyProvidedBy
+from zope.interface import directlyProvides
+
+from ocql.interfaces import IAlgebraOptimizer
+
+from ocql.interfaces import IAlgebraObject
+from ocql.interfaces import IOptimizedAlgebraObject
+
+def addMarkerIF(obj, marker):
+ obj = removeSecurityProxy(obj)
+ if not marker.providedBy(obj):
+ directlyProvides(obj, directlyProvidedBy(obj), marker)
+
+class AlgebraOptimizer(object):
+ implements(IAlgebraOptimizer)
+ adapts(IAlgebraObject)
+
+ def __init__(self, context):
+ self.context = context
+ #self.db = db
+
+ def __call__(self):
+ addMarkerIF(self.context, IOptimizedAlgebraObject)
+ return self.context
Property changes on: Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/aoptimizer.py
___________________________________________________________________
Name: svn:keywords
+ Date Author Id Revision
Name: svn:eol-style
+ native
Added: Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/aoptimizer.txt
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/aoptimizer.txt (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/aoptimizer.txt 2008-06-15 14:35:58 UTC (rev 87410)
@@ -0,0 +1,25 @@
+
+
+ >>> from ocql.aoptimizer.aoptimizer import AlgebraOptimizer
+ >>> from ocql.interfaces import 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
+
+ >>> in_=Dummy('foo-bar')
+ >>> in_.value
+ 'foo-bar'
+
+ >>> out = AlgebraOptimizer(in_)()
+
+ >>> print out
+ <Dummy object at ...>
+ >>> out.value
+ 'foo-bar'
+
+ >>> IOptimizedAlgebraObject.providedBy(out)
+ True
\ No newline at end of file
Property changes on: Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/aoptimizer.txt
___________________________________________________________________
Name: svn:keywords
+ Date Author Id Revision
Name: svn:eol-style
+ native
Added: Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/tests.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/tests.py (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/tests.py 2008-06-15 14:35:58 UTC (rev 87410)
@@ -0,0 +1,14 @@
+import unittest
+import doctest
+from zope.testing.doctestunit import DocTestSuite,DocFileSuite
+
+def test_suite():
+ flags = doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS
+ return unittest.TestSuite((
+ DocFileSuite('aoptimizer.txt',
+ optionflags=flags),
+ ))
+
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
Property changes on: Sandbox/adamg/ocql/trunk/src/ocql/aoptimizer/tests.py
___________________________________________________________________
Name: svn:keywords
+ Date Author Id Revision
Name: svn:eol-style
+ native
Added: Sandbox/adamg/ocql/trunk/src/ocql/compiler/compiler.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/compiler/compiler.py (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/compiler/compiler.py 2008-06-15 14:35:58 UTC (rev 87410)
@@ -0,0 +1,31 @@
+# -*- coding: UTF-8 -*-
+
+"""Compiles Algebra Object to python code
+
+$Id$
+"""
+
+#BIG-BIG-BIG TODO:
+# move all class.compile to here, using the adapter pattern
+
+from zope.component import adapts
+from zope.interface import implements
+
+from ocql.interfaces import IAlgebraCompiler
+from ocql.interfaces import IOptimizedAlgebraObject
+
+from ocql.compiler.runnablequery import RunnableQuery
+
+class AlgebraCompiler(object):
+ implements(IAlgebraCompiler)
+ adapts(IOptimizedAlgebraObject)
+
+ def __init__(self, context):
+ self.context = context
+ #self.db = db
+
+ def __call__(self, metadata, algebra):
+ algebra = self.context
+ code = algebra.compile()
+ run = RunnableQuery(metadata, algebra, code)
+ return run
\ No newline at end of file
Property changes on: Sandbox/adamg/ocql/trunk/src/ocql/compiler/compiler.py
___________________________________________________________________
Name: svn:keywords
+ Date Author Id Revision
Name: svn:eol-style
+ native
Added: Sandbox/adamg/ocql/trunk/src/ocql/compiler/compiler.txt
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/compiler/compiler.txt (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/compiler/compiler.txt 2008-06-15 14:35:58 UTC (rev 87410)
@@ -0,0 +1,67 @@
+
+I'm sorry, but I'm lazy here, in reality we would have to create
+stubs for all ocql.rewriter.algebra classes and use those...
+But it's a lot faster to reuse the parser and the existing classes.
+
+ >>> 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.testing.database import TestMetadata
+
+ >>> metadata = TestMetadata()
+ >>> qo = QueryParser("set [ | 1 ]")(metadata)
+ >>> opt = QueryOptimizer(qo)()
+ >>> alg = Rewriter(opt)()
+ >>> aopt = AlgebraOptimizer(alg)()
+ >>> run = AlgebraCompiler(aopt)(metadata, alg)
+ >>> print str(run)
+ RunnableQuery: set([1])
+
+
+ >>> metadata = TestMetadata()
+ >>> qo = QueryParser("set [ | 1 ] union set [|2]")(TestMetadata())
+ >>> opt = QueryOptimizer(qo)()
+ >>> alg = Rewriter(opt)()
+ >>> aopt = AlgebraOptimizer(alg)()
+ >>> run = AlgebraCompiler(aopt)(metadata, alg)
+ >>> print str(run)
+ RunnableQuery: set.union(set([1]),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`))
+
+
+
+ >>> metadata = TestMetadata()
+ >>> qo = QueryParser("set [ i in ICourse | i ]")(TestMetadata())
+ >>> opt = QueryOptimizer(qo)()
+ >>> alg = Rewriter(opt)()
+ >>> aopt = AlgebraOptimizer(alg)()
+ >>> run = AlgebraCompiler(aopt)(metadata, alg)
+ >>> print str(run)
+ RunnableQuery: reduce(set.union, map(lambda i: set([i]),set(metadata.getAll("ICourse"))) , set())
+
+
+ ##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))
+
+ >>> metadata = TestMetadata()
+ >>> qo = QueryParser("set [ c in ICourse | c.code ]")(TestMetadata())
+ >>> opt = QueryOptimizer(qo)()
+ >>> alg = Rewriter(opt)()
+ >>> aopt = AlgebraOptimizer(alg)()
+ >>> run = AlgebraCompiler(aopt)(metadata, alg)
+ >>> print str(run)
+ RunnableQuery: reduce(set.union, map(lambda c: set([c.code]),set(metadata.getAll("ICourse"))) , set())
\ No newline at end of file
Property changes on: Sandbox/adamg/ocql/trunk/src/ocql/compiler/compiler.txt
___________________________________________________________________
Name: svn:keywords
+ Date Author Id Revision
Name: svn:eol-style
+ native
Added: Sandbox/adamg/ocql/trunk/src/ocql/compiler/runnablequery.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/compiler/runnablequery.py (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/compiler/runnablequery.py 2008-06-15 14:35:58 UTC (rev 87410)
@@ -0,0 +1,78 @@
+# -*- coding: UTF-8 -*-
+
+"""Runnable query object
+This will return the resultset
+
+$Id$
+"""
+
+import operator
+
+from ocql.interfaces import IAlgebraOptimizer
+from ocql.interfaces import IAlgebraCompiler
+
+_marker = object()
+
+def d_reduce(function, sequence, initializer=_marker):
+ if initializer is _marker:
+ rv = reduce(function, sequence)
+ else:
+ rv = reduce(function, sequence, initializer)
+ return rv
+
+def d_map(function, *sequences):
+ #print "Mapping from", [i for i in sequences[0]]
+ rv = map(function, *sequences)
+ return rv
+
+def d_range(start, stop):
+ rv = range(start, stop)
+ return rv
+
+class d_set(set):
+ def union(self, other):
+ rv = set.union(self, other)
+ return rv
+
+ def __call__(self):
+ rv = set.__call__(self)
+ return rv
+
+ def __init__(self, list=[]):
+ #print "creating set with values", list
+ rv = set.__init__(self, list)
+ return rv
+
+
+
+class RunnableQuery:
+ """
+ metadata: ocql.metadata instance
+ alg: algebra object
+ """
+ def __init__(self, metadata, alg, code):
+ self.metadata = metadata
+ self.alg = alg
+ self.code =code
+
+ def __repr__(self):
+ return "%s: %s" % (self.__class__.__name__,
+ self.code)
+
+ def reanalyze(self):
+ optimizedalgebra = IAlgebraOptimizer(self.alg)()
+ runnable = IAlgebraCompiler(optimizedalgebra)(self.metadata, self.alg)
+ return runnable
+
+ def execute(self, debug=False):
+ #TODO: why is the metadata not working in locals?
+
+ mapping = {'metadata': self.metadata,
+ 'operator': operator}
+ if debug:
+ mapping['reduce'] = d_reduce
+ mapping['map'] = d_map
+ mapping['range'] = d_range
+ mapping['set'] = d_set
+
+ return eval(self.code, mapping, mapping)
Property changes on: Sandbox/adamg/ocql/trunk/src/ocql/compiler/runnablequery.py
___________________________________________________________________
Name: svn:keywords
+ Date Author Id Revision
Name: svn:eol-style
+ native
Added: Sandbox/adamg/ocql/trunk/src/ocql/compiler/tests.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/compiler/tests.py (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/compiler/tests.py 2008-06-15 14:35:58 UTC (rev 87410)
@@ -0,0 +1,14 @@
+import unittest
+import doctest
+from zope.testing.doctestunit import DocTestSuite,DocFileSuite
+
+def test_suite():
+ flags = doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS
+ return unittest.TestSuite((
+ DocFileSuite('compiler.txt',
+ optionflags=flags),
+ ))
+
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
Property changes on: Sandbox/adamg/ocql/trunk/src/ocql/compiler/tests.py
___________________________________________________________________
Name: svn:keywords
+ Date Author Id Revision
Name: svn:eol-style
+ native
Added: Sandbox/adamg/ocql/trunk/src/ocql/database/__init__.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/database/__init__.py (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/database/__init__.py 2008-06-15 14:35:58 UTC (rev 87410)
@@ -0,0 +1 @@
+#
\ No newline at end of file
Property changes on: Sandbox/adamg/ocql/trunk/src/ocql/database/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Date Author Id Revision
Name: svn:eol-style
+ native
Added: Sandbox/adamg/ocql/trunk/src/ocql/database/metadata.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/database/metadata.py (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/database/metadata.py 2008-06-15 14:35:58 UTC (rev 87410)
@@ -0,0 +1,28 @@
+class MetaType:
+ def get_property(self, name):
+ """
+ Get type information and metadata for property.
+ Returns a MetaType
+ """
+
+ def is_collection(self):
+ """Returns True if the represented type is a collection."""
+
+ def get_collection_type(self):
+ """Returns the represented type"""
+
+ def get_contained(self):
+ """
+ Throws an exception if represented type is not a collection, or
+ the contained type if a collection
+ """
+
+ def get_size(self):
+ """Returns the size of the collection or class if known"""
+
+class Metadata:
+ def __init__(self):
+ pass
+
+ def get_class(self, classname):
+ """Returns a MetaType instance for the class."""
\ No newline at end of file
Property changes on: Sandbox/adamg/ocql/trunk/src/ocql/database/metadata.py
___________________________________________________________________
Name: svn:keywords
+ Date Author Id Revision
Name: svn:eol-style
+ native
Modified: Sandbox/adamg/ocql/trunk/src/ocql/engine.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/engine.py 2008-06-15 12:38:04 UTC (rev 87409)
+++ Sandbox/adamg/ocql/trunk/src/ocql/engine.py 2008-06-15 14:35:58 UTC (rev 87410)
@@ -31,12 +31,12 @@
def compile(self, query):
#TODO: later use maybe named adapters
- db = IDB(None)
+ metadata = IDB(None)
- objectquery = IQueryParser(query)()
+ objectquery = IQueryParser(query)(metadata)
optimizedoq = IQueryOptimizer(objectquery)()
algebra = IRewriter(optimizedoq)()
optimizedalgebra = IAlgebraOptimizer(algebra)()
- runnable = IAlgebraCompiler(optimizedalgebra)()
+ runnable = IAlgebraCompiler(optimizedalgebra)(metadata, algebra)
return runnable
\ No newline at end of file
Added: Sandbox/adamg/ocql/trunk/src/ocql/parser/parser.txt
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/parser/parser.txt (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/parser/parser.txt 2008-06-15 14:35:58 UTC (rev 87410)
@@ -0,0 +1,36 @@
+
+
+ >>> from ocql.parser.queryparser import QueryParser
+
+
+
+ #FAILS, why?
+ #>>> QueryParser("set [ ]")(None)
+ #Query(<type 'set'>, , Constant(1))
+
+ >>> QueryParser("set [ | 1 ]")(None)
+ Query(<type 'set'>, , Constant(1))
+
+ #FAILS, why?
+ #>>> QueryParser("list [ | 1 ]")(None)
+ #Query(<type 'set'>, , Constant(1))
+
+ >>> QueryParser("set [ | 1 ] union set [|2]")(None)
+ Union(Query(<type 'set'>, , Constant(1)), Query(<type 'set'>, , Constant(2)))
+
+ >>> QueryParser("set [ | 1 ] differ set [|2]")(None)
+ Differ(Query(<type 'set'>, , Constant(1)), Query(<type 'set'>, , Constant(2)))
+
+ >>> QueryParser("set [ i in ICourse | i ]")(None)
+ Query(<type 'set'>, In(Identifier(i), Identifier(ICourse)), Identifier(i))
+
+ >>> QueryParser("size set [ i in ICourse | i ]")(None)
+ Count(Query(<type 'set'>, In(Identifier(i), Identifier(ICourse)), Identifier(i)))
+
+ #FAILS, see raise "Help"
+ #>>> QueryParser("set [ d in IDepartments; every set [ c in ICourse; some c.runBy == d | c.credits ] == 2 | d.name ]")(None)
+
+ #>>> QueryParser("set [ c in ICourse; c.credits>3 | c.code ]")(None)
+
+ >>> QueryParser("set [ c in ICourse | c.code ]")(None)
+ Query(<type 'set'>, In(Identifier(c), Identifier(ICourse)), Property(Identifier(c), Identifier(code)))
\ No newline at end of file
Property changes on: Sandbox/adamg/ocql/trunk/src/ocql/parser/parser.txt
___________________________________________________________________
Name: svn:keywords
+ Date Author Id Revision
Name: svn:eol-style
+ native
Added: Sandbox/adamg/ocql/trunk/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-06-15 14:35:58 UTC (rev 87410)
@@ -0,0 +1,465 @@
+# -*- coding: UTF-8 -*-
+
+"""Parse a string to Query Object
+
+$Id$
+"""
+
+#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
+import zope.thread
+
+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)
+
+ #print 'add'
+ #print self.stack
+
+ def dellevel(self):
+ self.stack.pop()
+
+ #print 'del'
+ #print self.stack
+
+ def current(self):
+ return self.stack[-1]
+
+tokens = ('TYPE', 'UNION', 'DIFFER', 'AND', 'OR', 'NOT', 'ELLIPSIS', 'IN',
+ 'AS', 'SIZE', 'COND_OP', 'MODIFIER', 'QUANTOR', 'CONSTANT',
+ 'IDENTIFIER', 'PLUS', 'MINUS', 'MUL', 'DIV', 'BRACEL', 'BRACER',
+ 'SQUAREL', 'SQUARER', 'CURLYL', 'CURLYR',
+ 'PIPE', 'DOT', 'SEMICOL', 'COMMA'
+ )
+
+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', 'SEMICOL'),
+
+ ('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)
+
+ # Tokens
+ def t_TYPE(self, t):
+ r'(set|bag|map)'
+ return t
+
+ def t_UNION(self, t):
+ r'union'
+ return t
+
+ def t_DIFFER(self, t):
+ r'differ'
+ return t
+
+ def t_AND(self, t):
+ r'and'
+ return t
+
+ def t_OR(self, t):
+ r'or'
+ return t
+
+ def t_NOT(self, t):
+ r'not'
+ return t
+
+ def t_ELLIPSIS(self, t):
+ r'\.\.\.'
+ return t
+
+ def t_IN(self, t):
+ r'in'
+ return t
+
+ def t_AS(self, t):
+ r'as'
+ return t
+
+ def t_SIZE(self, t):
+ r'size'
+ return t
+
+ def t_COND_OP(self, t):
+ r'(<|>|<=|>=|==|!=)'
+ return t
+
+ def t_MODIFIER(self, t):
+ r'(atleast|atmost|just)'
+ return t
+
+ def t_QUANTOR(self, t):
+ r'(every|some)'
+ 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_]*'
+ if DEBUG: print "IDEN", t
+ return t
+
+ def t_PLUS(self, t):
+ r'\+'
+ return t
+
+ def t_MINUS(self, t):
+ r'-'
+ return t
+
+ def t_MUL(self, t):
+ r'\*'
+ return t
+
+ def t_DIV(self, t):
+ r'/'
+ return t
+
+ def t_BRACEL(self, t):
+ r'\('
+ return t
+
+ def t_BRACER(self, t):
+ r'\)'
+ return t
+
+ def t_SQUAREL(self, t):
+ r'\['
+ return t
+
+ def t_SQUARER(self, t):
+ r'\]'
+ return t
+
+ def t_CURLYL(self, t):
+ r'{'
+ return t
+
+ def t_CURLYR(self, t):
+ r'}'
+ return t
+
+ def t_PIPE(self, t):
+ r'\|'
+ return t
+
+ def t_DOT(self, t):
+ r'\.'
+ return t
+
+ def t_SEMICOL(self, t):
+ r';'
+ return t
+
+ def t_COMMA(self, t):
+ r','
+ return t
+
+class Parser(object):
+ tokens = tokens
+ precedence = precedence
+ metadata = None
+ symbols = None
+ types = { 'set' : set, 'list': list }
+ start = 'expr'
+
+ 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_cond(self, t):
+ r'''expr : modifier nexpr COND_OP omodifier nexpr
+ | expr COND_OP omodifier nexpr'''
+ raise "Help"
+
+ def p_expr_union(self, t):
+ r'''expr : expr UNION expr
+ nexpr : nexpr UNION nexpr
+ '''
+ t[0] = Union(self.metadata, self.symbols, t[1], t[3])
+ if DEBUG: print t[0]
+
+ def p_expr_differ(self, t):
+ r'''expr : expr DIFFER expr
+ nexpr : nexpr DIFFER nexpr
+ '''
+ t[0] = Differ(self.metadata, self.symbols, t[1], t[3])
+ if DEBUG: print t[0]
+
+ def p_expr_query(self, t):
+ r'''expr : TYPE SQUAREL xprs PIPE expr SQUARER
+ nexpr : TYPE SQUAREL xprs PIPE expr SQUARER
+ '''
+ t[0] = Query(self.metadata, self.symbols, self.types[t[1]], t[3], t[5])
+ if DEBUG: print "p_expr_query", t[0]
+
+ def p_expr_and(self, t):
+ r'''expr : expr AND expr
+ nexpr : nexpr AND nexpr
+ '''
+ t[0] = And(self.metadata, self.symbols, t[1], t[3])
+ if DEBUG: print t[0]
+
+ def p_expr_or(self, t):
+ r'''expr : expr OR expr
+ nexpr : nexpr OR nexpr
+ '''
+ t[0] = Or(self.metadata, self.symbols, t[1], t[3])
+ if DEBUG: print t[0]
+
+ def p_expr_plus(self, t):
+ r'''expr : expr PLUS expr
+ nexpr : nexpr PLUS nexpr
+ '''
+ t[0] = Add(self.metadata, self.symbols, t[1], t[3])
+ if DEBUG: print t[0]
+
+ def p_expr_minus(self, t):
+ r'''expr : expr MINUS expr
+ nexpr : nexpr MINUS nexpr
+ '''
+ t[0] = Sub(self.metadata, self.symbols, t[1], t[3])
+ if DEBUG: print t[0]
+
+ def p_expr_mul(self, t):
+ r'''expr : expr MUL expr
+ nexpr : nexpr MUL nexpr
+ '''
+ t[0] = Mul(self.metadata, self.symbols, t[1], t[3])
+ if DEBUG: print t[0]
+
+ def p_expr_div(self, t):
+ r'''expr : expr DIV expr
+ nexpr : nexpr DIV nexpr
+ '''
+ t[0] = Div(self.metadata, self.symbols, t[1], t[3])
+ if DEBUG: print t[0]
+
+ def p_expr_not(self, t):
+ r'''expr : NOT expr
+ nexpr : NOT nexpr
+ '''
+ t[0] = Not(self.metadata, self.symbols, t[2])
+ if DEBUG: print t[0]
+
+ def p_expr_dot(self, t):
+ r'''expr : expr DOT expr
+ nexpr : nexpr DOT expr
+ '''
+ t[0] = Property(self.metadata, self.symbols, t[1], t[3])
+ if DEBUG: print t[0]
+
+ def p_expr_id(self, t):
+ r'''expr : IDENTIFIER
+ nexpr : IDENTIFIER
+ '''
+ t[0] = Identifier(self.metadata, self.symbols, t[1])
+ if DEBUG: print "p_expr_id", t[0]
+
+
+ def p_expr_call(self, t):
+ r'''expr : IDENTIFIER BRACEL exprs BRACER
+ nexpr : IDENTIFIER BRACEL exprs BRACER
+ '''
+ raise NotImplementedError("Function call")
+
+ def p_expr_const(self, t):
+ r'''expr : CONSTANT
+ nexpr : CONSTANT
+ '''
+ t[0] = Constant(self.metadata, self.symbols, t[1])
+ if DEBUG: print t[0]
+
+ def p_expr_array(self, t):
+ r'''expr : TYPE '{' exprs '}'
+ nexpr : TYPE '{' exprs '}'
+ '''
+ raise NotImplementedError("array")
+
+ def p_expr_range(self, t):
+ r'''expr : TYPE CURLYL expr ELLIPSIS expr CURLYR
+ nexpr : TYPE CURLYL expr ELLIPSIS expr CURLYR
+ '''
+ raise NotImplementedError("range")
+
+
+ def p_expr_index(self, t):
+ r'''expr : expr DOT SQUAREL expr SQUARER
+ nexpr : nexpr DOT SQUAREL expr SQUARER
+ '''
+ t[0] = Index(self.metadata, self.symbols, t[1], t[4])
+ if DEBUG: print t[0]
+
+ def p_expr_size(self, t):
+ r'''expr : SIZE expr
+ nexpr : SIZE expr
+ '''
+ t[0] = Count(self.metadata, self.symbols, t[2])
+ if DEBUG: print t[0]
+
+ def p_expr_bracket(self, t):
+ r'''expr : BRACEL expr BRACER
+ nexpr : BRACEL expr BRACEL
+ '''
+ t[0] = t[2]
+ if DEBUG: print t[0]
+
+ def p_omodifier(self, t):
+ r'''omodifier : QUANTOR
+ | MODIFIER
+ '''
+ if DEBUG: print t[0]
+
+ def p_modifier(self, t):
+ r'''modifier : QUANTOR
+ | MODIFIER
+ '''
+ if DEBUG: print t[0]
+
+ def p_exprs(self, t):
+ r'''exprs : expr
+ | expr COMMA exprs
+ '''
+ if DEBUG: print t[0]
+
+ def p_in_expr(self, t):
+ r'''in_expr : IDENTIFIER IN expr'''
+ t[0] = In(self.metadata,
+ self.symbols,
+ Identifier(self.metadata,
+ self.symbols,
+ t[1]),
+ t[3])
+ if DEBUG: print "p_in_expr", t[0]
+ if DEBUG: print t[1], t[3]
+
+ def p_as_expr(self, t):
+ r'''as_expr : IDENTIFIER AS expr'''
+ if DEBUG: print "p_as_expr", t[0]
+
+ def p_xprs(self, t):
+ r'''xprs :
+ | xpr SEMICOL xprs
+ | xpr
+ '''
+ if len(t)==1:
+ t[0] = []
+ elif len(t)==2:
+ t[0] = [ t[1] ]
+ else:
+ t[3].insert(t[0], 0)
+ t[0] = t[3]
+ if DEBUG: print "p_xprs", t[0]
+
+ def p_xpr(self, t):
+ r'''xpr : as_expr
+ | in_expr
+ | expr
+ '''
+ t[0] = t[1]
+ if DEBUG: print "p_xpr", 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
+ return parse(strg, metadata)
+ #return parse(strg, None)
Property changes on: Sandbox/adamg/ocql/trunk/src/ocql/parser/queryparser.py
___________________________________________________________________
Name: svn:keywords
+ Date Author Id Revision
Name: svn:eol-style
+ native
Added: Sandbox/adamg/ocql/trunk/src/ocql/parser/tests.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/parser/tests.py (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/parser/tests.py 2008-06-15 14:35:58 UTC (rev 87410)
@@ -0,0 +1,14 @@
+import unittest
+import doctest
+from zope.testing.doctestunit import DocTestSuite,DocFileSuite
+
+def test_suite():
+ flags = doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS
+ return unittest.TestSuite((
+ DocFileSuite('parser.txt',
+ optionflags=flags),
+ ))
+
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
Property changes on: Sandbox/adamg/ocql/trunk/src/ocql/parser/tests.py
___________________________________________________________________
Name: svn:keywords
+ Date Author Id Revision
Name: svn:eol-style
+ native
Added: Sandbox/adamg/ocql/trunk/src/ocql/qoptimizer/qoptimizer.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/qoptimizer/qoptimizer.py (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/qoptimizer/qoptimizer.py 2008-06-15 14:35:58 UTC (rev 87410)
@@ -0,0 +1,34 @@
+# -*- coding: UTF-8 -*-
+
+""" Optimizing will be done later,
+at the moment this is just a stub returning it's input
+
+$Id$
+"""
+
+from zope.component import adapts
+from zope.interface import implements
+from zope.security.proxy import removeSecurityProxy
+from zope.interface import directlyProvidedBy
+from zope.interface import directlyProvides
+
+from ocql.interfaces import IQueryOptimizer
+
+from ocql.interfaces import IObjectQuery
+from ocql.interfaces import IOptimizedObjectQuery
+
+def addMarkerIF(obj, marker):
+ obj = removeSecurityProxy(obj)
+ if not marker.providedBy(obj):
+ directlyProvides(obj, directlyProvidedBy(obj), marker)
+
+class QueryOptimizer(object):
+ implements(IQueryOptimizer)
+ adapts(IObjectQuery)
+
+ def __init__(self, context):
+ self.context = context
+
+ def __call__(self):
+ addMarkerIF(self.context, IOptimizedObjectQuery)
+ return self.context
\ No newline at end of file
Property changes on: Sandbox/adamg/ocql/trunk/src/ocql/qoptimizer/qoptimizer.py
___________________________________________________________________
Name: svn:keywords
+ Date Author Id Revision
Name: svn:eol-style
+ native
Added: Sandbox/adamg/ocql/trunk/src/ocql/qoptimizer/qoptimizer.txt
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/qoptimizer/qoptimizer.txt (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/qoptimizer/qoptimizer.txt 2008-06-15 14:35:58 UTC (rev 87410)
@@ -0,0 +1,25 @@
+
+
+ >>> from ocql.qoptimizer.qoptimizer import QueryOptimizer
+ >>> from ocql.interfaces import IOptimizedObjectQuery
+
+Currently the optimizer is doing NOTHING, it just returns what it gets.
+(And adds the interface IOptimizedObjectQuery)
+
+ >>> class Dummy(object):
+ ... def __init__(self, value):
+ ... self.value = value
+
+ >>> in_=Dummy('foo-bar')
+ >>> in_.value
+ 'foo-bar'
+
+ >>> out = QueryOptimizer(in_)()
+
+ >>> print out
+ <Dummy object at ...>
+ >>> out.value
+ 'foo-bar'
+
+ >>> IOptimizedObjectQuery.providedBy(out)
+ True
\ No newline at end of file
Property changes on: Sandbox/adamg/ocql/trunk/src/ocql/qoptimizer/qoptimizer.txt
___________________________________________________________________
Name: svn:keywords
+ Date Author Id Revision
Name: svn:eol-style
+ native
Added: Sandbox/adamg/ocql/trunk/src/ocql/qoptimizer/tests.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/qoptimizer/tests.py (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/qoptimizer/tests.py 2008-06-15 14:35:58 UTC (rev 87410)
@@ -0,0 +1,14 @@
+import unittest
+import doctest
+from zope.testing.doctestunit import DocTestSuite,DocFileSuite
+
+def test_suite():
+ flags = doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS
+ return unittest.TestSuite((
+ DocFileSuite('qoptimizer.txt',
+ optionflags=flags),
+ ))
+
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
Property changes on: Sandbox/adamg/ocql/trunk/src/ocql/qoptimizer/tests.py
___________________________________________________________________
Name: svn:keywords
+ Date Author Id Revision
Name: svn:eol-style
+ native
Added: Sandbox/adamg/ocql/trunk/src/ocql/queryobject/__init__.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/queryobject/__init__.py (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/queryobject/__init__.py 2008-06-15 14:35:58 UTC (rev 87410)
@@ -0,0 +1 @@
+#
\ No newline at end of file
Property changes on: Sandbox/adamg/ocql/trunk/src/ocql/queryobject/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Date Author Id Revision
Name: svn:eol-style
+ native
Added: Sandbox/adamg/ocql/trunk/src/ocql/queryobject/queryobject.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/queryobject/queryobject.py (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/queryobject/queryobject.py 2008-06-15 14:35:58 UTC (rev 87410)
@@ -0,0 +1,539 @@
+# -*- coding: UTF-8 -*-
+
+"""Classes for the Query Object representation
+
+$Id$
+"""
+
+#TODOS:
+#write Interfaces for all classes
+
+#move self.rewrite to ocql.rewriter into adapters
+
+#add self.__repr__ to ALL, see Query class
+
+#implement a traversable tree of queryobjects (parent, child, sibling, ....)
+
+from zope.interface import implements
+
+from ocql.interfaces import IObjectQuery
+
+class QueryObject:
+ #TODO: this is dirty here, at the end we'll need to have a tree of
+ #QueryObject's whose topmost element will only get this IF
+ implements(IObjectQuery)
+
+ metadata = None
+ symbols = None
+
+ def __init__(self, metadata, symbols):
+ self.metadata = metadata
+ self.symbols = symbols
+
+ def addSymbol(self):
+ pass
+
+ def get_class(self):
+ s = self.symbols.current()
+ try:
+ return s[self.name]
+ except KeyError:
+ return self.metadata.get_class(self.name)
+ except AttributeError:
+ from pub.dbgpclient import brk; brk()
+
+
+ def get_collection_type(self, klass=None):
+ if klass is None:
+ klass = self.get_class()
+
+ if klass is None:
+ from pub.dbgpclient import brk; brk()
+
+ rv = klass.get_collection_type()
+ #print self.name,rv
+ return rv
+
+ def rewrite(self, algebra):
+ raise NotImplementedError(self)
+
+class Term:
+ pass
+
+class Expression(Term, QueryObject):
+ pass
+
+#
+# General
+#
+class hasClassWith(Expression):
+ #NotImplementedError
+ expression = None
+ klass = None
+ conditional = None
+
+ def __init__(self, metadata, symbols, expr, klass, conditional):
+ self.metadata = metadata
+ self.symbols = symbols
+ self.expression = expr
+ self.klass = klass
+ self.conditional = conditional
+
+class Identifier(Expression):
+ name = None
+
+ def __init__(self, metadata, symbols, name):
+ self.metadata = metadata
+ self.symbols = symbols
+ self.name = name
+
+ def __repr__(self):
+ return "%s(%s)" % (
+ self.__class__.__name__,
+ str(self.name),
+ )
+
+ def rewrite(self, algebra):
+ return algebra.Identifier(self.name)
+
+class Constant(Expression):
+ #this shall be abstract?
+ value = None
+
+ def __init__(self, metadata, symbols, value):
+ self.metadata = metadata
+ self.symbols = symbols
+ self.value=value
+
+ def __repr__(self):
+ return "%s(%s)" % (
+ self.__class__.__name__, self.value)
+
+ def rewrite(self, algebra):
+ return algebra.Constant(self.value)
+
+class StringConstant(Constant):
+ pass
+
+class NumericConstant(Constant):
+ #TODO: convert value to string?
+ pass
+
+class BooleanConstant(Constant):
+ #TODO: convert value to string?
+ pass
+
+class CollectionConstant(Constant):
+ pass
+
+class Query(Expression):
+ collection_type = None
+ terms = None
+ target = None
+
+ def __init__(self, metadata, symbols, collection_type, terms, target):
+ self.metadata = metadata
+ self.symbols = symbols
+ self.collection_type = collection_type
+ self.terms = terms
+ self.target = target
+
+ def __repr__(self):
+ return "%s(%s, %s, %s)" % (
+ self.__class__.__name__,
+ str(self.collection_type),
+ '; '.join([str(t) for t in self.terms]),
+ str(self.target)
+ )
+
+ def get_collection_type(self, klass=None):
+ return self.collection_type
+
+ def rewrite(self, algebra):
+ self.symbols.addlevel()
+ rv=None
+
+ if len(self.terms):
+ for t in self.terms:
+ t.addSymbol()
+
+ firstTerm = self.terms[0]
+ if isinstance(firstTerm, In):
+
+ ctype = firstTerm.get_collection_type()
+
+ rv = algebra.Iter(
+ self.collection_type,
+ algebra.Lambda(
+ firstTerm.identifier.name,
+ Query(
+ self.metadata,
+ self.symbols,
+ self.collection_type,
+ self.terms[1:],
+ self.target
+ ).rewrite(algebra)
+ ), algebra.Make(
+ self.collection_type,
+ ctype,
+ firstTerm.expression.rewrite(algebra)
+ ) # FIXME: ?set? must be determined by type(firstTerm.expression)
+ )
+ elif isinstance(firstTerm, Alias):
+ rv = Query(
+ self.metadata,
+ self.collection_type,
+ [In(
+ self.metadata,
+ firstTerm.identifier,
+ firstTerm.expression
+ )]+self.terms[1:],
+ self.target).rewrite(algebra)
+ else:
+ rv = algebra.If(
+ firstTerm.rewrite(algebra),
+ Query(
+ self.metadata,
+ self.collection_type,
+ self.terms[1:],
+ self.target).rewrite(algebra),
+ algebra.Empty(self.collection_type, None)
+ )
+ else:
+ rv = algebra.Single(
+ self.collection_type,
+ self.target.rewrite(algebra))
+
+ self.symbols.dellevel()
+ return rv
+
+class In(Term):
+ identifier = None
+ expression = None
+
+ def __init__(self, metadata, symbols, identifier, expression):
+ self.metadata = metadata
+ self.symbols = symbols
+ self.identifier = identifier
+ self.expression = expression
+
+ def __repr__(self):
+ return "%s(%s, %s)" % (
+ self.__class__.__name__,
+ str(self.identifier),
+ str(self.expression)
+ )
+
+ def addSymbol(self):
+ s = self.symbols.current()
+ #s[self.identifier.name] = self.metadata.get_class(
+ # self.expression.name)
+ s[self.identifier.name] = self.expression.get_class()
+
+ def get_collection_type(self):
+ rv = self.expression.get_collection_type()
+ return rv
+
+class Alias(Term):
+ identifier = None
+ expression = None
+
+ def __init__(self, metadata, symbols, identifier, expression):
+ self.metadata = metadata
+ self.symbols = symbols
+ self.identifier = identifier
+ self.expression = expression
+
+ def __repr__(self):
+ return "%s(%s, %s)" % (
+ self.__class__.__name__,
+ str(self.identifier),
+ str(self.expression)
+ )
+
+ def addSymbol(self):
+ s = self.symbols.current()
+ #TODO: that's not really good
+ r = self.expression.get_collection_type()
+
+ s[self.identifier.name] = r
+
+ def get_collection_type(self):
+ rv = self.expression.get_collection_type()
+ #print self.expression.name,rv
+ return rv
+
+#
+# Binary operators
+#
+class Binary(Expression):
+ left = None
+ right = None
+
+ def __init__(self, metadata, symbols, left, right):
+ self.metadata = metadata
+ self.symbols = symbols
+ self.left = left
+ self.right = right
+
+ def __repr__(self):
+ return "%s(%s, %s)" % (
+ self.__class__.__name__,
+ str(self.left), str(self.right)
+ )
+
+ def rewrite(self, algebra):
+ return algebra.Binary(
+ self.left.rewrite(algebra),
+ self.get_operator(algebra),
+ self.right.rewrite(algebra))
+
+# Sets and properties
+class Union(Binary):
+ def rewrite(self, algebra):
+ return algebra.Union(
+ self.left.get_collection_type(),
+ self.left.rewrite(algebra),
+ self.right.rewrite(algebra))
+
+class Differ(Binary):
+ def rewrite(self, algebra):
+ return algebra.Differ(
+ self.left.get_collection_type(),
+ self.left.rewrite(algebra),
+ self.right.rewrite(algebra))
+
+class And(Binary):
+ def get_operator(self, algebra):
+ return algebra.Operator('and')
+
+class Or(Binary):
+ def get_operator(self, algebra):
+ return algebra.Operator('or')
+
+class Property(Binary):
+ def rewrite(self, algebra): # FIXME: Ezt gondold at...
+ return algebra.Identifier(
+ '.'.join([self.left.name, self.right.name]))
+
+ def get_class(self):
+ t = self.left.get_class()
+
+ return t
+
+ def get_collection_type(self):
+ t = self.left.get_class()
+ try:
+ r = t[self.right.name]
+ except:
+ from pub.dbgpclient import brk; brk()
+
+ #print self.left.name+'.'+self.right.name,r
+
+ return r
+
+class Index(Binary):
+ #NotImplementedError
+ pass
+
+
+# Arithmetic operators
+class Arithmetic(Binary):
+ pass
+
+class Add(Arithmetic):
+ def get_operator(self, algebra):
+ return algebra.Operator('+')
+
+class Mul(Arithmetic):
+ def get_operator(self, algebra):
+ return algebra.Operator('*')
+
+class Sub(Arithmetic):
+ def get_operator(self, algebra):
+ return algebra.Operator('-')
+
+class Div(Arithmetic):
+ def get_operator(self, algebra):
+ return algebra.Operator('/')
+
+#
+# Unary operators
+#
+class Unary(Expression):
+ expression = None
+
+ def __init__(self, metadata, symbols, expression):
+ self.metadata = metadata
+ self.symbols = symbols
+ self.expression = expression
+
+ def __repr__(self):
+ return "%s(%s)" % (
+ self.__class__.__name__,
+ str(self.expression)
+ )
+
+class Not(Unary):
+ def rewrite(self, algebra):
+ return algebra.Not(self.expression.rewrite(algebra))
+
+class Aggregate(Unary):
+ pass
+
+class Count(Aggregate):
+ def rewrite(self, algebra):
+ return algebra.Reduce(
+ bag, # FIXME milyen bag
+ 0,
+ algebra.Lambda('i', algebra.Constant(1)),
+ algebra.Operator('+'),
+ make(bag, set, self.expression.rewrite(algebra))
+ # FIXME ?set? must be determined by type(self.expression)
+ )
+
+class Sum(Aggregate):
+ #NotImplementedError
+ pass
+
+#
+# Conditional
+#
+class Quantor(QueryObject):
+ def rewrite(self, algebra, expression, quanter, operator):
+ raise NotImplementedError()
+
+class Quanted:
+ quantor = None
+ expression = None
+
+ def __init__(self, metadata, symbols, quantor, expression):
+ self.metadata = metadata
+ self.symbols = symbols
+ self.quantor = quantor
+ self.expression = expression
+
+ def rewrite(self, algebra, expression, operator):
+ return self.quantor.rewrite(algebra, expression, self.expression, operator)
+
+# Quantors
+class Every(Quantor):
+ def rewrite(self, algebra, expression, quanted, operator):
+ ctype = quanted.get_collection_type()
+
+ return algebra.Reduce(
+ ctype, # FIXME ?set? but which type() to take? quanted.expression?
+ algebra.Identifier('True'),
+ algebra.Lambda('i',
+ operator.__class__(
+ self.metadata,
+ Identifier(
+ self.metadata,
+ 'i'),
+ expression
+ ).rewrite(algebra)
+ ),
+ algebra.Operator('and'),
+ quanted.rewrite(algebra)
+ )
+
+class Some(Quantor):
+ def rewrite(self, algebra, expression, quanted, operator):
+ ctype = quanted.get_collection_type()
+ return algebra.Reduce(
+ ctype, # FIXME ?set? but which type() to take? quanted.expression?
+ algebra.Identifier('False'),
+ algebra.Lambda('i',
+ operator.__class__(
+ self.metadata,
+ Identifier(self.metadata, 'i'),
+ expression
+ ).rewrite(algebra)
+ ),
+ algebra.Operator('or'),
+ quanted.rewrite(algebra)
+ )
+
+class Atmost(Quantor):
+ expr = None
+
+ def __init__(self, metadata, symbols, expr):
+ raise NotImplementedError(self)
+ self.metadata = metadata
+ self.symbols = symbols
+ self.expr = expr
+
+class Atleast(Quantor):
+ expr = None
+
+ def __init__(self, metadata, symbols, expr):
+ raise NotImplementedError(self)
+ self.metadata = metadata
+ self.symbols = symbols
+ self.expr = expr
+
+class Just(Quantor):
+ expr = None
+
+ def __init__(self, metadata, symbols, expr):
+ raise NotImplementedError(self)
+ self.metadata = metadata
+ self.symbols = symbols
+ self.expr = expr
+
+# Logical operators
+class Condition(Expression):
+ left = None
+ right = None
+
+ def __init__(self, metadata, symbols, left, right):
+ self.metadata = metadata
+ self.symbols = symbols
+ self.left = left
+ self.right = right
+
+ def rewrite(self, algebra):
+ if isinstance(self.left, Quanted):
+ return self.left.rewrite(
+ algebra,
+ self.right,
+ self)
+ if isinstance(self.right, Quanted):
+ return self.right.rewrite(
+ algebra,
+ self.left,
+ self)
+ else:
+ return algebra.Binary(self.left.rewrite(algebra), self.get_operator(algebra), self.right.rewrite(algebra))
+
+class Eq(Condition):
+ def get_operator(self, algebra):
+ return algebra.Operator('==')
+
+class Ne(Condition):
+ def get_operator(self, algebra):
+ return algebra.Operator('!=')
+
+class Lt(Condition):
+ def get_operator(self, algebra):
+ return algebra.Operator('<')
+
+class Gt(Condition):
+ def get_operator(self, algebra):
+ return algebra.Operator('>')
+
+class Le(Condition):
+ def get_operator(self, algebra):
+ return algebra.Operator('<=')
+
+class Ge(Condition):
+ def get_operator(self, algebra):
+ return algebra.Operator('>=')
+
+# TODO: missing:
+ #xi{Es}
+ #xi{E1..E2}
+ #I(Es)
+ #K
+ #==,
+ #~==
Property changes on: Sandbox/adamg/ocql/trunk/src/ocql/queryobject/queryobject.py
___________________________________________________________________
Name: svn:keywords
+ Date Author Id Revision
Name: svn:eol-style
+ native
Added: Sandbox/adamg/ocql/trunk/src/ocql/rewriter/algebra.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/rewriter/algebra.py (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/rewriter/algebra.py 2008-06-15 14:35:58 UTC (rev 87410)
@@ -0,0 +1,417 @@
+# -*- coding: UTF-8 -*-
+
+"""Algebra operators
+
+$Id$
+"""
+
+#
+# decided to let these depend on the database
+# so this is the implementation
+#
+
+from zope.interface import implements
+
+from ocql.interfaces import IAlgebraObject
+
+class Algebra:
+ """Signature definition of Algebra operation classes.
+ shall be moved to an IF later
+ """
+ #TODO: this is dirty here, at the end we'll need to have a tree of
+ #Algebra's whose topmost element will only get this IF
+ implements(IAlgebraObject)
+
+ def compile(self):
+ """Return the compiled python code"""
+
+ def walk(self):
+ """Iterate the Algebra object tree"""
+
+class BaseAlgebra(Algebra):
+ pass
+
+class Empty(BaseAlgebra):
+ """
+ >>> Empty(set,None).compile()
+ 'set()'
+ >>> Empty(list,None).compile()
+ '[]'
+ """
+ def __init__(self, klass, expr):
+ self.klass = klass
+
+ def compile(self):
+ if self.klass==set:
+ return 'set()'
+ elif self.klass==list:
+ return '[]'
+
+ def __repr__(self):
+ return 'Empty(%s)'%(self.klass)
+
+ def walk(self):
+ yield self
+
+class Single(BaseAlgebra):
+ """
+ >>> Single(set,Constant('c')).compile()
+ 'set([c])'
+ >>> Single(list,Constant('c')).compile()
+ '[c]'
+ """
+
+ def __init__(self, klass, expr):
+ self.klass = klass
+ self.expr = expr
+
+ def compile(self):
+ if self.klass==set:
+ return 'set(['+self.expr.compile()+'])'
+ elif self.klass==list:
+ return '['+self.expr.compile()+']'
+
+ def __repr__(self):
+ return 'Single(%s,%s)'%(self.klass, self.expr)
+
+ def walk(self):
+ yield self
+ for t in self.expr.walk():
+ yield t
+
+class Union(BaseAlgebra):
+ """
+ >>> Union(set,Empty(set,None),Single(set,Identifier('c'))).compile()
+ 'set.union(set(),set([c]))'
+ >>> Union(list,Empty(list,None),Single(list,Identifier('c'))).compile()
+ '([])+([c])'
+ """
+ def __init__(self, klass, coll1, coll2):
+ self.klass=klass
+ self.coll1=coll1
+ self.coll2=coll2
+
+ def compile(self):
+ if self.klass==set:
+ return 'set.union(%s,%s)' % (
+ self.coll1.compile(),
+ self.coll2.compile())
+ elif self.klass==list:
+ return '(%s)+(%s)'%(
+ self.coll1.compile(),
+ self.coll2.compile())
+
+ def __repr__(self):
+ return 'Union(%s,%s,%s)'%(self.klass, self.coll1, self.coll2)
+
+ def walk(self):
+ yield self
+ for t in self.coll1.walk():
+ yield t
+ for t in self.coll2.walk():
+ yield t
+
+#class Differ:
+# def __init__(self, klass, start, end):
+# self.klass = klass
+# self.start = start
+# self.end = end
+#
+# def compile(self):
+# if self.klass == set:
+# return 'set(range(%s,%s))' % (self.start.compile(),self.end.compile())
+# if self.klass == list:
+# return 'range(%s,%s)' % (self.start.compile(),self.end.compile())
+
+
+class Iter(BaseAlgebra):
+ def __init__(self, klass, func, coll):
+ self.klass = klass
+ self.func = func
+ self.coll = coll
+
+ def compile(self):
+ if self.func is Lambda and \
+ self.coll is Collection and \
+ self.func.expr is If:
+
+ # You can place here some specialized code...
+ if self.klass == set:
+ return 'reduce(set.union, map(%s,%s) , set())' % \
+ (self.func.compile(), self.coll.compile())
+ if self.klass == list:
+ return 'reduce(operator.add, map(%s,%s) , [])' % \
+ (self.func.compile(), self.coll.compile())
+ else:
+ if self.klass == set:
+ return 'reduce(set.union, map(%s,%s) , set())' % \
+ (self.func.compile(), self.coll.compile())
+ if self.klass == list:
+ return 'reduce(operator.add, map(%s,%s) , [])' % \
+ (self.func.compile(), self.coll.compile())
+
+ def __repr__(self):
+ return "Iter(%s,%s,%s)"%(self.klass, self.func, self.coll)
+
+ def walk(self):
+ yield self
+ for t in self.func.walk():
+ yield t
+ for t in self.coll.walk():
+ yield t
+
+class Select(BaseAlgebra):
+ def __init__(self, klass, func, coll):
+ self.klass = klass
+ self.func = func
+ self.coll = coll
+
+ def compile(self):
+ if self.klass == set:
+ return 'set(filter(%s,%s))' % (
+ self.func.compile(),
+ self.coll.compile())
+ if self.klass == list:
+ return 'filter(%s,%s)' % (
+ self.func.compile(),
+ self.coll.compile())
+
+ def __repr__(self):
+ return "Select(%s,%s,%s)"%(self.klass, self.func, self.coll)
+
+ def walk(self):
+ yield self
+ for t in self.func.walk():
+ yield t
+ for t in self.coll.walk():
+ yield t
+
+class Reduce(BaseAlgebra):
+ def __init__(self, klass, expr, func, aggreg, coll):
+ self.klass = klass
+ self.expr = expr
+ self.func = func
+ self.aggreg = aggreg
+ self.coll = coll
+
+ def compile(self):
+ if self.klass == set:
+ return 'reduce(%s,map(%s,%s),%s)' % (
+ self.aggreg.compile(),
+ self.func.compile(),
+ self.coll.compile(),
+ self.expr.compile())
+ if self.klass == list:
+ return 'reduce(%s,map(%s,%s),%s)' % (
+ self.aggreg.compile(),
+ self.func.compile(),
+ self.coll.compile(),
+ self.expr.compile())
+
+ def __repr__(self):
+ return "Reduce(%s,%s,%s,%s,%s)"%(self.klass, self.expr, self.func, self.aggreg, self.coll)
+
+ def walk(self):
+ yield self
+ for t in self.expr.walk():
+ yield t
+ for t in self.func.walk():
+ yield t
+ for t in self.aggreg.walk():
+ yield t
+ for t in self.coll.walk():
+ yield t
+
+#class Equal:
+# def __init__(self, klass, coll1, coll2):
+# self.klass = klass
+# self.coll1 = coll1
+# self.coll2 = coll2
+#
+# def compile(self):
+# if self.klass == set:
+# 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())
+#
+class Range(BaseAlgebra):
+ def __init__(self, klass, start, enf):
+ self.klass = klass
+ self.start = start
+ self.end = end
+
+ def compile(self):
+ if self.klass == set:
+ return 'set(range(%s,%s))' % (
+ self.start.compile(),
+ self.end.compile())
+ if self.klass == list:
+ return 'range(%s,%s)' % (
+ self.start.compile(),
+ self.end.compile())
+
+ def walk(self):
+ yield self
+ for t in self.start.walk():
+ yield t
+ for t in self.end.walk():
+ yield t
+
+
+#class Index
+
+class Make(BaseAlgebra):
+ def __init__(self, coll1, coll2, expr):
+ self.expr = expr
+ self.coll1 = coll1
+ self.coll2 = coll2
+
+ def compile(self):
+ #TODO: no conversion??? or you just didn't know the from-to?
+ return '%s(metadata.getAll("%s"))' % (
+ self.coll1.__name__,
+ self.expr.compile())
+
+ def __repr__(self):
+ return "Make(%s,%s,%s)" %(self.coll1, self.coll2, self.expr)
+
+ def walk(self):
+ yield self
+ for t in self.expr.walk():
+ yield t
+
+#class And:
+#class Being:
+
+class If(BaseAlgebra):
+ def __init__(self, cond, expr1, expr2):
+ self.cond = cond
+ self.expr1 = expr1
+ self.expr2 = expr2
+
+ def compile(self):
+ #TODO: is this 100%?
+ return '((%s) and (%s) or (%s))' % (
+ self.cond.compile(),
+ self.expr1.compile(),
+ self.expr2.compile())
+
+ def __repr__(self):
+ return "If(%s,%s,%s)" % (self.cond, self.expr1, self.expr2)
+
+ def walk(self):
+ yield self
+ for t in self.cond.walk():
+ yield t
+ for t in self.expr1.walk():
+ yield t
+ for t in self.expr2.walk():
+ yield t
+
+#
+#
+#
+class Lambda(BaseAlgebra):
+ def __init__(self, var, expr):
+ self.var = var
+ self.expr = expr
+
+ def compile(self):
+ return 'lambda %s: %s'%(
+ self.var,
+ self.expr.compile())
+
+ def __repr__(self):
+ return "Lambda %s: %s" %(self.var, self.expr)
+
+ def walk(self):
+ yield self
+ for t in self.expr.walk():
+ yield t
+
+class Constant(BaseAlgebra):
+ def __init__(self, value):
+ self.value = value
+
+ def compile(self):
+ return '%s'%(self.value)
+
+ def __repr__(self):
+ return "`%s`" %(self.value)
+
+ def walk(self):
+ yield self
+
+class Identifier(BaseAlgebra):
+ def __init__(self, name):
+ self.name=name
+
+ def compile(self):
+ return self.name
+
+ def __repr__(self):
+ return "%s" % self.name
+
+ def walk(self):
+ yield self
+
+class Binary(BaseAlgebra):
+ def __init__(self, left, op, right):
+ self.left = left
+ self.op = op
+ self.right = right
+
+ def compile(self):
+ return '%s%s%s' % (self.left.compile(),
+ self.op.op,
+ self.right.compile())
+
+ def __repr__(self):
+ return "%s%s%s" % (self.left, self.op.op, self.right)
+
+ def walk(self):
+ yield self
+ for t in self.left.walk():
+ yield t
+ for t in self.right.walk():
+ yield t
+
+class Operator(BaseAlgebra):
+ ops = {
+ 'or': 'operator.or_',
+ 'and': 'operator.and_',
+ 'not': 'operator.not_',
+ '+': 'operator.add', '-': 'operator.sub',
+ '*': 'operator.mul', '/': 'operator.div',
+ '<': 'operator.lt', '>': 'operator.gt',
+ '<=': 'operator.le', '>=': 'operator.ge',
+ '==': 'operator.eq', '~=': 'operator.ne',
+ }
+ def __init__(self, op):
+ self.op = op
+
+ def compile(self):
+ return self.ops[self.op]
+
+ def __repr__(self):
+ return self.op
+
+ def walk(self):
+ yield self
+#class Property:
+# def __init__(self, left, right):
+# self.left = left
+# self.right = right
+#
+# def compile(self):
+# return '%s.%s' (self.left.compile(),self.right.compile())
+#
+# def __repr__(self):
+# return '%s.%s' (self.left,self.right)
+
+def _test():
+ import doctest
+ doctest.testmod()
+
+if __name__ == "__main__":
+ _test()
Property changes on: Sandbox/adamg/ocql/trunk/src/ocql/rewriter/algebra.py
___________________________________________________________________
Name: svn:keywords
+ Date Author Id Revision
Name: svn:eol-style
+ native
Added: Sandbox/adamg/ocql/trunk/src/ocql/rewriter/rewriter.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/rewriter/rewriter.py (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/rewriter/rewriter.py 2008-06-15 14:35:58 UTC (rev 87410)
@@ -0,0 +1,29 @@
+# -*- coding: UTF-8 -*-
+
+"""Rewrites the Query Object to Algebra Object
+
+$Id$
+"""
+
+#BIG-BIG-BIG TODO:
+# move all queryobject.rewrite to this package
+# using adapters to do the rewrite
+
+from zope.component import adapts
+from zope.interface import implements
+
+from ocql.interfaces import IRewriter
+from ocql.interfaces import IOptimizedObjectQuery
+
+from ocql.rewriter import algebra as target_algebra
+
+class Rewriter(object):
+ implements(IRewriter)
+ adapts(IOptimizedObjectQuery)
+
+ def __init__(self, context):
+ self.context = context
+
+ def __call__(self):
+ query = self.context
+ return query.rewrite(target_algebra)
Property changes on: Sandbox/adamg/ocql/trunk/src/ocql/rewriter/rewriter.py
___________________________________________________________________
Name: svn:keywords
+ Date Author Id Revision
Name: svn:eol-style
+ native
Added: Sandbox/adamg/ocql/trunk/src/ocql/rewriter/rewriter.txt
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/rewriter/rewriter.txt (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/rewriter/rewriter.txt 2008-06-15 14:35:58 UTC (rev 87410)
@@ -0,0 +1,50 @@
+
+I'm sorry, but I'm lazy here, in reality we would have to create
+stubs for all ocql.queryobject classes and use those...
+But it's a lot faster to reuse the parser and the existing classes.
+
+Add queries first to parser.txt doctest, after they pass there they can be
+added here.
+
+ >>> from ocql.parser.queryparser import QueryParser
+ >>> from ocql.qoptimizer.qoptimizer import QueryOptimizer
+ >>> from ocql.rewriter.rewriter import Rewriter
+
+ >>> from ocql.testing.database import TestMetadata
+
+
+ >>> qo = QueryParser("set [ | 1 ]")(TestMetadata())
+ >>> opt = QueryOptimizer(qo)()
+ >>> alg = Rewriter(opt)()
+ >>> print str(alg)
+ Single(<type 'set'>,`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`))
+
+
+ #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)()
+ >>> print str(alg)
+ Iter(<type 'set'>,Lambda i: Single(<type 'set'>,i),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
Property changes on: Sandbox/adamg/ocql/trunk/src/ocql/rewriter/rewriter.txt
___________________________________________________________________
Name: svn:keywords
+ Date Author Id Revision
Name: svn:eol-style
+ native
Added: Sandbox/adamg/ocql/trunk/src/ocql/rewriter/tests.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/rewriter/tests.py (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/rewriter/tests.py 2008-06-15 14:35:58 UTC (rev 87410)
@@ -0,0 +1,15 @@
+import unittest
+import doctest
+from zope.testing.doctestunit import DocTestSuite,DocFileSuite
+
+def test_suite():
+ flags = doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS
+ return unittest.TestSuite((
+ DocFileSuite('rewriter.txt',
+ optionflags=flags),
+ DocTestSuite('ocql.rewriter.algebra')
+ ))
+
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
Property changes on: Sandbox/adamg/ocql/trunk/src/ocql/rewriter/tests.py
___________________________________________________________________
Name: svn:keywords
+ Date Author Id Revision
Name: svn:eol-style
+ native
Added: Sandbox/adamg/ocql/trunk/src/ocql/testing/database.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/testing/database.py (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/testing/database.py 2008-06-15 14:35:58 UTC (rev 87410)
@@ -0,0 +1,136 @@
+from zope.component import adapts
+from zope.component import provideAdapter
+from zope.interface import implements
+
+from zope.interface import Interface, implements
+from zope.schema import TextLine, Set, Choice, Int, List
+
+from ocql.interfaces import IDB
+from ocql.database import metadata
+
+# schema
+class ICourse(Interface):
+ code = TextLine(
+ title=u"Course code",
+ required=True
+ )
+ runBy = List(
+ title=u"Run by",
+ value_type = Choice(
+ title=u"Department",
+ vocabulary="vocab_of_IDepartment",
+ )
+ )
+ credits = Int(
+ title=u"Credits",
+ )
+
+class IDepartments(Interface):
+ name = TextLine(
+ title=u"name",
+ required=True
+ )
+ address = Choice(
+ title=u"Street address",
+ vocabulary="vocab_of_IAddress",
+ required=True
+ )
+
+class MClass(metadata.MetaType):
+ #interface suspect thing
+ def __init__(self, klass):
+ self.klass = klass
+
+ def is_collection(self):
+ return True
+
+ def get_collection_type(self):
+ return set
+
+ def get_contained(self):
+ return self.klass
+
+ def __getitem__(self, name):
+ x = self.klass[name]._type
+ try:
+ return x[-1]
+ except TypeError:
+ return x
+
+class MType(metadata.MetaType):
+ def __init__(self, klass, collection_type=None):
+ self.klass = klass
+ self.collection_type = collection_type
+
+ def is_collection(self):
+ return (self.collection_type is not None)
+
+ def get_collection_type(self):
+ return self.collection_type
+
+ def get_contained(self):
+ return self.klass
+
+class Department(object):
+ implements(IDepartments)
+
+ def __init__(self, name):
+ self.name = name
+
+ def __repr__(self):
+ return "%s <%s>" % (
+ self.__class__.__name__,
+ self.name
+ )
+
+class Course(object):
+ implements(ICourse)
+
+ def __init__(self, code, runBy, credits):
+ self.code = code
+ self.runBy = runBy
+ self.credits = credits
+
+ def __repr__(self):
+ return "%s <%s>" % (
+ self.__class__.__name__,
+ self.code
+ )
+
+D1 = Department("Computing Science")
+D2 = Department("Other department")
+D3 = Department("Department without curse")
+
+C1 = Course("C1", runBy = set([D1, D2]), credits=2)
+C2 = Course("C2", runBy = set(), credits=3)
+C3 = Course("C3", runBy = set([D1]), credits=3)
+
+
+# metadata
+class TestMetadata(metadata.Metadata):
+ implements(IDB)
+ adapts(None)
+
+ db = {
+ 'IDepartments': [D1, D2],
+ 'ICourse': [C1, C2, C3]
+ }
+ classes = {
+ 'IDepartments': MClass(IDepartments),
+ 'ICourse': MClass(ICourse),
+ }
+
+ def __init__(self, context=None):
+ pass
+
+ def getAll(self, klass):
+ x=self.db[klass]
+ 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
Property changes on: Sandbox/adamg/ocql/trunk/src/ocql/testing/database.py
___________________________________________________________________
Name: svn:keywords
+ Date Author Id Revision
Name: svn:eol-style
+ native
Modified: Sandbox/adamg/ocql/trunk/src/ocql/testing/stubs.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/testing/stubs.py 2008-06-15 12:38:04 UTC (rev 87409)
+++ Sandbox/adamg/ocql/trunk/src/ocql/testing/stubs.py 2008-06-15 14:35:58 UTC (rev 87410)
@@ -45,7 +45,7 @@
self.context = context
#self.db = db
- def __call__(self):
+ def __call__(self, metadata):
strg = self.context
return ObjectQueryTree()
@@ -88,7 +88,7 @@
self.context = context
#self.db = db
- def __call__(self):
+ def __call__(self, metadata, algebra):
return RunnableQuery()
class DB(object):
Added: Sandbox/adamg/ocql/trunk/src/ocql/tests/run.txt
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/tests/run.txt (rev 0)
+++ Sandbox/adamg/ocql/trunk/src/ocql/tests/run.txt 2008-06-15 14:35:58 UTC (rev 87410)
@@ -0,0 +1,79 @@
+
+Now we'll see how a query runs
+
+ >>> 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.testing.database import TestMetadata
+
+ >>> provideAdapter(QueryParser)
+ >>> provideAdapter(QueryOptimizer)
+ >>> provideAdapter(Rewriter)
+ >>> provideAdapter(AlgebraOptimizer)
+ >>> provideAdapter(AlgebraCompiler)
+ >>> provideAdapter(TestMetadata)
+
+ >>> from ocql.engine import OCQLEngine
+
+
+ >>> engine = OCQLEngine()
+ >>> run = engine.compile("set [ | 1 ]")
+ >>> run
+ RunnableQuery: set([1])
+
+ >>> result = run.execute()
+ >>> result
+ set([1])
+
+ >>> type(result)
+ <type 'set'>
+
+
+
+ >>> engine = OCQLEngine()
+ >>> run = engine.compile("set [ | 1 ] union set [|2]")
+ >>> run
+ RunnableQuery: set.union(set([1]),set([2]))
+
+ >>> result = run.execute()
+ >>> result
+ set([1, 2])
+
+ >>> type(result)
+ <type 'set'>
+
+
+
+ >>> 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())
+
+ >>> result = run.execute()
+ >>> result
+ set([Course <C1>, Course <C2>, Course <C3>])
+
+ >>> type(result)
+ <type 'set'>
+
+
+
+ >>> 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())
+
+ >>> result = run.execute()
+ >>> result
+ set(['C3', 'C2', 'C1'])
+
+ >>> type(result)
+ <type 'set'>
+
+ >>> run = run.reanalyze()
+ >>> run.execute()
+ set(['C3', 'C2', 'C1'])
\ No newline at end of file
Property changes on: Sandbox/adamg/ocql/trunk/src/ocql/tests/run.txt
___________________________________________________________________
Name: svn:keywords
+ Date Author Id Revision
Name: svn:eol-style
+ native
Modified: Sandbox/adamg/ocql/trunk/src/ocql/tests/test_skeleton.py
===================================================================
--- Sandbox/adamg/ocql/trunk/src/ocql/tests/test_skeleton.py 2008-06-15 12:38:04 UTC (rev 87409)
+++ Sandbox/adamg/ocql/trunk/src/ocql/tests/test_skeleton.py 2008-06-15 14:35:58 UTC (rev 87410)
@@ -6,6 +6,8 @@
"""
import unittest
+import doctest
+from zope.testing.doctestunit import DocTestSuite,DocFileSuite
from ocql.engine import OCQLEngine
from ocql.testing.stubs import *
@@ -15,14 +17,16 @@
registerStubs()
e = OCQLEngine()
- rq = e.compile("[ c in ICurses | c ]")
+ rq = e.compile("[ c in ICourse | c ]")
self.assert_(isinstance(rq, RunnableQuery))
def test_suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(testSkeleton))
- return suite
+ flags = doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS
+ return unittest.TestSuite((
+ unittest.makeSuite(testSkeleton),
+ DocFileSuite('run.txt', optionflags=flags),
+ ))
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
\ No newline at end of file
More information about the Checkins
mailing list