39 self.selection = [var.name.upper() for var in sparqlst.selected] |
40 self.selection = [var.name.upper() for var in sparqlst.selected] |
40 self.possible_types = {} |
41 self.possible_types = {} |
41 self.infer_types_info = [] |
42 self.infer_types_info = [] |
42 self.union_params = [] |
43 self.union_params = [] |
43 self.restrictions = [] |
44 self.restrictions = [] |
44 |
45 self.literals = {} |
45 def finalize(self): |
46 self._litcount = 0 |
46 """return corresponding rql query""" |
47 |
47 for varname, ptypes in self.possible_types.iteritems(): |
48 def add_literal(self, value): |
48 if len(ptypes) == 1: |
49 key = chr(ord('a') + self._litcount) |
49 self.restrictions.append('%s is %s' % (varname, iter(ptypes).next())) |
50 self._litcount += 1 |
50 unions = [] |
51 self.literals[key] = value |
51 for releq, subjvar, objvar in self.union_params: |
52 return key |
52 thisunions = [] |
|
53 for st, rt, ot in releq: |
|
54 thisunions.append(['%s %s %s' % (subjvar, rt, objvar)]) |
|
55 if st != '*': |
|
56 thisunions[-1].append('%s is %s' % (subjvar, st)) |
|
57 if ot != '*': |
|
58 thisunions[-1].append('%s is %s' % (objvar, ot)) |
|
59 if not unions: |
|
60 unions = thisunions |
|
61 else: |
|
62 unions = zip(*make_domains([unions, thisunions])) |
|
63 selection = 'Any ' + ', '.join(self.selection) |
|
64 sparqlst = self.sparqlst |
|
65 if sparqlst.distinct: |
|
66 selection = 'DISTINCT ' + selection |
|
67 if not unions: |
|
68 return '%s%s WHERE %s' % (selection, order_limit_offset(sparqlst), |
|
69 ', '.join(self.restrictions)) |
|
70 baserql = '%s WHERE %s' % (selection, ', '.join(self.restrictions)) |
|
71 rqls = ['(%s, %s)' % (baserql, ', '.join(unionrestrs)) |
|
72 for unionrestrs in unions] |
|
73 rql = ' UNION '.join(rqls) |
|
74 if sparqlst.orderby or sparqlst.limit or sparqlst.offset: |
|
75 rql = '%s%s WITH %s BEING (%s)' % ( |
|
76 selection, order_limit_offset(sparqlst), |
|
77 ', '.join(self.selection), rql) |
|
78 return rql |
|
79 |
53 |
80 def set_possible_types(self, var, varpossibletypes): |
54 def set_possible_types(self, var, varpossibletypes): |
81 """set/restrict possible types for the given variable. |
55 """set/restrict possible types for the given variable. |
82 |
56 |
83 :return: True if something changed, else false. |
57 :return: True if something changed, else false. |
129 # ensure this still make sense |
103 # ensure this still make sense |
130 if not yams_predicates: |
104 if not yams_predicates: |
131 raise TypeResolverException() |
105 raise TypeResolverException() |
132 if len(yams_predicates) != nbchoices: |
106 if len(yams_predicates) != nbchoices: |
133 modified = True |
107 modified = True |
|
108 |
|
109 def build_restrictions(self): |
134 # now, for each predicate |
110 # now, for each predicate |
135 for yams_predicates, subjvar, obj in self.infer_types_info: |
111 for yams_predicates, subjvar, obj in self.infer_types_info: |
136 rel = yams_predicates[0] |
112 rel = yams_predicates[0] |
137 objvar = obj.name.upper() |
|
138 # if there are several yams relation type equivalences, we will have |
113 # if there are several yams relation type equivalences, we will have |
139 # to generate several unioned rql queries |
114 # to generate several unioned rql queries |
140 for s, r, o in yams_predicates[1:]: |
115 for s, r, o in yams_predicates[1:]: |
141 if r != rel[1]: |
116 if r != rel[1]: |
142 self.union_params.append((yams_predicates, subjvar, objvar)) |
117 self.union_params.append((yams_predicates, subjvar, obj)) |
143 break |
118 break |
|
119 # else we can simply add it to base rql restrictions |
144 else: |
120 else: |
145 # else we can simply add it to base rql restrictions |
121 restr = self.build_restriction(subjvar, rel[1], obj) |
146 self.restrictions.append('%s %s %s' % (subjvar, rel[1], objvar)) |
122 self.restrictions.append(restr) |
|
123 |
|
124 def build_restriction(self, subjvar, rtype, obj): |
|
125 if isinstance(obj, ast.SparqlLiteral): |
|
126 key = self.add_literal(obj.value) |
|
127 objvar = '%%(%s)s' % key |
|
128 else: |
|
129 assert isinstance(obj, ast.SparqlVar) |
|
130 # make a valid rql var name |
|
131 objvar = obj.name.upper() |
|
132 # else we can simply add it to base rql restrictions |
|
133 return '%s %s %s' % (subjvar, rtype, objvar) |
|
134 |
|
135 def finalize(self): |
|
136 """return corresponding rql query (string) / args (dict)""" |
|
137 for varname, ptypes in self.possible_types.iteritems(): |
|
138 if len(ptypes) == 1: |
|
139 self.restrictions.append('%s is %s' % (varname, iter(ptypes).next())) |
|
140 unions = [] |
|
141 for releq, subjvar, obj in self.union_params: |
|
142 thisunions = [] |
|
143 for st, rt, ot in releq: |
|
144 thisunions.append([self.build_restriction(subjvar, rt, obj)]) |
|
145 if st != '*': |
|
146 thisunions[-1].append('%s is %s' % (subjvar, st)) |
|
147 if isinstance(obj, ast.SparqlVar) and ot != '*': |
|
148 objvar = obj.name.upper() |
|
149 thisunions[-1].append('%s is %s' % (objvar, objvar)) |
|
150 if not unions: |
|
151 unions = thisunions |
|
152 else: |
|
153 unions = zip(*make_domains([unions, thisunions])) |
|
154 selection = 'Any ' + ', '.join(self.selection) |
|
155 sparqlst = self.sparqlst |
|
156 if sparqlst.distinct: |
|
157 selection = 'DISTINCT ' + selection |
|
158 if unions: |
|
159 baserql = '%s WHERE %s' % (selection, ', '.join(self.restrictions)) |
|
160 rqls = ['(%s, %s)' % (baserql, ', '.join(unionrestrs)) |
|
161 for unionrestrs in unions] |
|
162 rql = ' UNION '.join(rqls) |
|
163 if sparqlst.orderby or sparqlst.limit or sparqlst.offset: |
|
164 rql = '%s%s WITH %s BEING (%s)' % ( |
|
165 selection, order_limit_offset(sparqlst), |
|
166 ', '.join(self.selection), rql) |
|
167 else: |
|
168 rql = '%s%s WHERE %s' % (selection, order_limit_offset(sparqlst), |
|
169 ', '.join(self.restrictions)) |
|
170 return rql, self.literals |
147 |
171 |
148 |
172 |
149 class Sparql2rqlTranslator(object): |
173 class Sparql2rqlTranslator(object): |
150 def __init__(self, yschema): |
174 def __init__(self, yschema): |
151 self.yschema = yschema |
175 self.yschema = yschema |
174 # list of 3-uple |
198 # list of 3-uple |
175 # (yams etype (subject), yams rtype, yams etype (object)) |
199 # (yams etype (subject), yams rtype, yams etype (object)) |
176 # where subject / object entity type may '*' if not specified |
200 # where subject / object entity type may '*' if not specified |
177 yams_predicates = xy.yeq(':'.join(predicate)) |
201 yams_predicates = xy.yeq(':'.join(predicate)) |
178 qi.infer_types_info.append((yams_predicates, subjvar, obj)) |
202 qi.infer_types_info.append((yams_predicates, subjvar, obj)) |
179 if isinstance(obj, ast.SparqlVar): |
203 if not isinstance(obj, (ast.SparqlLiteral, ast.SparqlVar)): |
180 # make a valid rql var name |
|
181 objvar = obj.name.upper() |
|
182 else: |
|
183 raise UnsupportedQuery() |
204 raise UnsupportedQuery() |
184 qi.infer_types() |
205 qi.infer_types() |
|
206 qi.build_restrictions() |
185 return qi |
207 return qi |