WIP

authorFabien Amarger <fabien.amarger@logilab.fr>
changeset260a0abe2b47
branchdefault
phasedraft
hiddenno
parent revision#52ef7f9e2fc3 WIP
child revision<not specified>
files modified by this revision
cubicweb/sparql2rql.py
# HG changeset patch
# User Fabien Amarger <fabien.amarger@logilab.fr>
# Date 1587137068 -7200
# Fri Apr 17 17:24:28 2020 +0200
# Node ID 260a0abe2b47d43aa5f43cc1cfd54bd143842f01
# Parent 52ef7f9e2fc35b1f20f7b60762e36ac2b99ef3eb
WIP

diff --git a/cubicweb/sparql2rql.py b/cubicweb/sparql2rql.py
@@ -11,12 +11,13 @@
1  class UnsupportedQuery(Exception):
2      pass
3 
4 
5  class Sparql2RqlTranslator(object):
6 -    def __init__(self, string_query):
7 +    def __init__(self, string_query, cnx):
8          self.string_query = string_query
9 +        self.cnx = cnx
10          self.rql_query = ''
11          self.projected_variables = []
12          self.where = ''
13          self.offset = None
14          self.limit = None
@@ -56,12 +57,22 @@
15          return "%s %s %s" % (rql_subj, rql_pred, rql_obj)
16 
17      def eval_triples(self, p):
18          query = f"Any {','.join([variable.upper() for variable in p._vars])}"
19          query += f" WHERE {','.join([self.triple_translation(triple) for triple in p.triples])}"
20 -        print(query)
21 -        return [{'A': 4}]
22 +        rset = self.cnx.execute(query)
23 +        results = []
24 +        for row in rset:
25 +            solution = {}
26 +            has_error = False
27 +            for key, value in zip(rset.variables, row):
28 +                if value is None:
29 +                    has_error = True
30 +                solution[key] = value
31 +            if not has_error:
32 +                results.append(solution)
33 +        return results
34 
35      @staticmethod
36      def union(p1, p2):
37          return p1 + p2
38 
@@ -86,88 +97,91 @@
39                  result[variable] = value
40              except KeyError:
41                  result[variable] = value
42          for variable, value in s2.items():
43              try:
44 -                value1 = s1[variable]
45 +                s1[variable]
46              except KeyError:
47                  result[variable] = value
48          return result
49 
50 -    def translate(self, p):
51 +    def eval(self, p):
52          if not isinstance(p, CompValue):
53              return []
54 
55          if p.triples:
56              return self.eval_triples(p)
57 
58          if p.name == 'Join':
59 -            p1 = self.translate(p.p1)
60 -            p2 = self.translate(p.p2)
61 +            p1 = self.eval(p.p1)
62 +            p2 = self.eval(p.p2)
63              return self.join(p1, p2)
64 
65          if p.name == 'Union':
66 -            p1 = self.translate(p.p1)
67 -            p2 = self.translate(p.p2)
68 +            p1 = self.eval(p.p1)
69 +            p2 = self.eval(p.p2)
70              return self.union(p1, p2)
71 
72 -        if p.name == 'Minus':
73 -            return self.translate(p.p1) + ', NOT EXISTS (' + self.translate(p.p2) + ')'
74 
75 -        if p.length:
76 -            self.limit = p.length
77 +        # if p.length:
78 +            # self.limit = p.length
79 
80 -        if p.start:
81 -            self.offset = p.start
82 +        # if p.start:
83 +            # self.offset = p.start
84 
85 -        if p.name == 'Distinct':
86 -            self.distinct = True
87 +        # if p.name == 'Distinct':
88 +            # self.distinct = True
89 
90 -        if p.name == 'OrderBy':
91 -            for condition in p.expr:
92 -                self.orderby[self.variable_translation(condition.expr)] = condition.order
93 +        # if p.name == 'OrderBy':
94 +            # for condition in p.expr:
95 +                # self.orderby[self.variable_translation(condition.expr)] = condition.order
96 
97 -        for k in p:
98 -            return self.translate(p[k])
99 +        try:
100 +            return self.eval(p.p)
101 +        except KeyError:
102 +            raise UnsupportedQuery(f"{p.name} is not supported yet")
103 
104      def finalize(self):
105          limit = 'LIMIT %s ' % self.limit if self.limit else ''
106          offset = 'OFFSET %s ' % self.offset if self.offset else ''
107          distinct = 'DISTINCT ' if self.distinct else ''
108          orderby = 'ORDERBY %s ' % ','.join(
109              ['%s %s' % (var, order if order else '') for (var, order) in self.orderby.items()])
110          return '%sAny %s %s%s%sWHERE %s' % (
111              distinct, ','.join(self.projected_variables), orderby, limit, offset, self.where)
112 
113 -    @property
114 -    def rql(self):
115 +    def execute(self):
116          sparqlst = Query.parseString(self.string_query)
117          query_algebra = translateQuery(sparqlst).algebra
118          pprintAlgebra(translateQuery(sparqlst))
119 -        # print(query_algebra)
120          if query_algebra.name != "SelectQuery":
121              raise UnsupportedQuery()
122          self.projected_variables = [self.variable_translation(pv) for pv in query_algebra.PV]
123 -        self.where = self.translate(query_algebra.p)
124 -        return self.finalize()
125 +        return self.eval(query_algebra.p)
126 
127 
128 -if __name__ == '__main__':
129 +def test(cnx):
130      queryMinus = '''SELECT DISTINCT ?x WHERE {
131           ?x a <http://ns.cubicweb.org/cubicweb/0.0/Blog>
132           FILTER NOT EXISTS
133           {?x <http://ns.cubicweb.org/cubicweb/0.0/titi> <http://ns.cubicweb.org/cubicweb/0.0/Toto>}}
134 
135           '''
136 -    queryUnion = '''SELECT DISTINCT ?x ?y WHERE {
137 -         ?x <http://ns.cubicweb.org/cubicweb/0.0/name> ?y.
138 -         {?x a <http://ns.cubicweb.org/cubicweb/0.0/Blog>.}
139 +    queryUnion = '''
140 +    PREFIX cw: <http://ns.cubicweb.org/cubicweb/0.0/>
141 +    SELECT DISTINCT ?x ?y WHERE {
142 +         {?x a <http://ns.cubicweb.org/cubicweb/0.0/Blog>.
143 +         ?x cw:title ?y.}
144           UNION
145 -         {?x a <http://ns.cubicweb.org/cubicweb/0.0/CWUser>}
146 +         {?x a <http://ns.cubicweb.org/cubicweb/0.0/CWUser>.
147 +         ?x cw:firstname ?y.}
148           }
149           '''
150      # Any X, Y WITH X,Y BEING ((Any X WHERE X name Y, X is Blog) UNION (Any X WHERE X name Y, X is CWUser))
151 -    simpleQuery = '''SELECT ?x WHERE {
152 -        ?x a <http://ns.cubicweb.org/cubicweb/0.0/Blog>.
153 +    simpleQuery = '''
154 +    PREFIX cw: <http://ns.cubicweb.org/cubicweb/0.0/>
155 +    SELECT ?x ?n WHERE {
156 +        ?x a cw:Blog.
157 +        ?x cw:title ?n.
158      }'''
159 -    sq = Sparql2RqlTranslator(queryUnion)
160 -    print(sq.rql)
161 +    sq = Sparql2RqlTranslator(queryUnion, cnx)
162 +    print(sq.execute())