Commits

Brian Beck  committed 3177254

Preliminary, untested support for all query forms (ASK, CONSTRUCT, DESCRIBE, SELECT).

  • Participants
  • Parent commits 7fabc9f

Comments (0)

Files changed (3)

File lib/telescope/sparql/compiler.py

 from operator import itemgetter
 from rdflib import Literal, URIRef, Namespace
+from telescope.exceptions import *
 from telescope.sparql.expressions import *
 from telescope.sparql import operators
 from telescope.sparql.operators import FunctionCall
 from telescope.sparql.patterns import *
+from telescope.sparql.query import *
 from telescope.sparql.queryforms import *
 from telescope.sparql.helpers import RDF, XSD, is_a
 from telescope.sparql.util import defrag, to_variable, to_list
             yield self.operator(expression.operator)
         yield self.compile(expression.value)
 
-class SelectCompiler(Compiler):
+
+class QueryCompiler(Compiler):
+    HANDLERS = {}
+
+    @classmethod
+    def handle(cls, query_type):
+        cls.HANDLERS[query_type] = cls
+
+    @classmethod
+    def get_handler(cls, query_or_type):
+        if isinstance(query_or_type, SPARQLQuery):
+            return cls.get_handler(type(query_or_type))
+        elif isinstance(query_or_type, type):
+            try:
+                return cls.HANDLERS[query_or_type]
+            except KeyError:
+                type_base = query_or_type.__base__
+                if isinstance(type_base, type):
+                    return cls.get_handler(type_base)
+                else:
+                    raise
+        else:
+            raise TypeError
+
     def __init__(self, prefix_map=None):
         Compiler.__init__(self, prefix_map)
         self.expression_compiler = ExpressionCompiler(self.prefix_map)
     
-    def compile(self, select):
-        """Compile `select` and return the resulting string.
+    def compile(self, query):
+        """Compile `query` and return the resulting string.
         
-        `select` is a `telescope.sparql.select.Select` instance.
+        `query` is a `telescope.sparql.query.SPARQLQuery` instance.
         
         """
-        return join(self.clauses(select), '\n')
+        return join(self.clauses(query), '\n')
     
     def expression(self, expression, bracketed=False):
         """
         """
         return self.expression_compiler.compile(expression, bracketed)
     
-    def clauses(self, select):
-        for prefix in self.prefixes():
-            yield prefix
-        yield join(self.select(select))
-        yield join(self.where(select))
-        yield join(self.order_by(select))
-        yield join(self.limit(select))
-        yield join(self.offset(select))
+    def clauses(self, query):
+        yield join(self.prefixes(), '\n')
+        yield join(self.query_form(query))
+        yield join(self.where(query))
     
     def prefixes(self):
         prefixes = sorted(self.prefix_map.iteritems(), key=itemgetter(1))
         yield '%s:' % (prefix,)
         yield self.expression_compiler.term(namespace, False)
     
-    def select(self, select):
-        yield 'SELECT'
-        yield join(self.unique(select))
-        yield join(self.projection(select))
-    
-    def unique(self, select):
-        if select._distinct:
-            yield 'DISTINCT'
-        elif select._reduced:
-            yield 'REDUCED'
-    
-    def limit(self, select):
-        if select._limit is not None:
-            yield 'LIMIT'
-            yield select._limit
-    
-    def offset(self, select):
-        if select._offset not in (0, None):
-            yield 'OFFSET'
-            yield select._offset
-    
-    def order_by(self, select):
-        if select._order_by:
-            yield 'ORDER BY'
-            for expression in select._order_by:
-                yield self.expression(expression)
-    
-    def projection(self, select):
-        if '*' in select.projection:
-            yield '*'
-        else:
-            for variable in select.projection:
-                yield self.expression(variable)
-    
+    def query_form(self, query):
+        yield query.query_form
+
     def where(self, select):
         yield 'WHERE'
         yield join(self.graph_pattern(select._where))
         if not isinstance(constraint, FunctionCall):
             bracketed = True
         yield self.expression(constraint, bracketed)
+
+
+class SolutionModifierSupportingQueryCompiler(QueryCompiler):
+    def clauses(self, query):
+        yield join(self.prefixes(), '\n')
+        yield join(self.query_form(query))
+        yield join(self.where(query))
+        yield join(self.order_by(query))
+        yield join(self.limit(query))
+        yield join(self.offset(query))
+
+    def order_by(self, query):
+        if query._order_by:
+            yield 'ORDER BY'
+            for expression in query._order_by:
+                yield self.expression(expression)
+
+    def limit(self, query):
+        if query._limit is not None:
+            yield 'LIMIT'
+            yield query._limit
+    
+    def offset(self, query):
+        if query._offset not in (0, None):
+            yield 'OFFSET'
+            yield query._offset
+
+
+class ProjectionSupportingQueryCompiler(SolutionModifierSupportingQueryCompiler):
+    def query_form(self, query):
+        for token in super(ProjectionSupportingQueryCompiler, self).query_form(query):
+            yield token
+        for token in self.projection(query):
+            yield token
+
+    def projection(self, query):
+        if '*' in query.projection:
+            yield '*'
+        else:
+            for term in query.projection:
+                yield self.expression(term)
+
+
+class SelectCompiler(ProjectionSupportingQueryCompiler):
+    def projection(self, query):
+        if query._distinct:
+            yield 'DISTINCT'
+        elif query._reduced:
+            yield 'REDUCED'
+        for token in super(SelectCompiler, self).projection(query):
+            yield token
+
+
+class ConstructCompiler(SolutionModifierSupportingQueryCompiler):
+    pass
+
+
+QueryCompiler.handle(SPARQLQuery)
+SolutionModifierSupportingQueryCompiler.handle(SolutionModifierSupportingQuery)
+ProjectionSupportingQueryCompiler.handle(ProjectionSupportingQueryCompiler)
+SelectCompiler.handle(Select)
+ConstructCompiler.handle(Construct)
+

File lib/telescope/sparql/query.py

         instances to prefixed names to use in the compiled query.
         
         """
-        from telescope.sparql.compiler import SelectCompiler
-        compiler = SelectCompiler(prefix_map)
+        from telescope.sparql.compiler import QueryCompiler
+        handler = QueryCompiler.get_handler(self)
+        compiler = handler(prefix_map)
         return compiler.compile(self)
 
+
 class SolutionModifierSupportingQuery(SPARQLQuery):
     """
     Programmatically build a SPARQL query that supports the solution modifiers
         """
         return self._clone(_offset=offset)
 
+
 class ProjectionSupportingQuery(SolutionModifierSupportingQuery):
     """Programmatically build a SPARQL query that supports projection."""
     
             for variable in map(to_variable, to_list(arg)):
                 projection.append(variable)
         return self._clone(projection=tuple(projection))
+

File lib/telescope/sparql/queryforms.py

 class Ask(SPARQLQuery):
     """Programmatically build a SPARQL ASK query."""
 
+    query_form = 'ASK'
 
 class Construct(SolutionModifierSupportingQuery):
     """Programmatically build a SPARQL CONSTRUCT query."""
+
+    query_form = 'CONSTRUCT'
     
     def __init__(self, template, pattern=None, order_by=None, limit=None,
                  offset=None):
 class Select(ProjectionSupportingQuery):
     """Programmatically build a SPARQL SELECT query."""
     
+    query_form = 'SELECT'
+
     def __init__(self, projection, pattern=None, distinct=False,
                  reduced=False, order_by=None, limit=None, offset=None):
         super(Select, self).__init__(projection, pattern, order_by=order_by,
 
 class Describe(ProjectionSupportingQuery):
     """Programmatically build a SPARQL DESCRIBE query."""
+
+    query_form = 'DESCRIBE'
+