74 if eid not in neweids: |
74 if eid not in neweids: |
75 eschema(session.describe(eid)[0]).check_perm(session, 'read') |
75 eschema(session.describe(eid)[0]).check_perm(session, 'read') |
76 eidconsts[lhs.variable] = eid |
76 eidconsts[lhs.variable] = eid |
77 return eidconsts |
77 return eidconsts |
78 |
78 |
|
79 def _build_substep_query(select, origrqlst): |
|
80 """Finalize substep select query that should be executed to get proper |
|
81 selection of stuff to insert/update. |
|
82 |
|
83 Return None when no query actually needed, else the given select node that |
|
84 will be used as substep query. |
|
85 |
|
86 When select has nothing selected, search in origrqlst for restriction that |
|
87 should be considered. |
|
88 """ |
|
89 if select.selection: |
|
90 if origrqlst.where is not None: |
|
91 select.set_where(origrqlst.where.copy(select)) |
|
92 return select |
|
93 if origrqlst.where is None: |
|
94 return |
|
95 for rel in origrqlst.where.iget_nodes(Relation): |
|
96 # search for a relation which is neither a type restriction (is) nor an |
|
97 # eid specification (not neged eid with constant node |
|
98 if rel.neged(strict=True) or not ( |
|
99 rel.is_types_restriction() or |
|
100 (rel.r_type == 'eid' |
|
101 and isinstance(rel.get_variable_parts()[1], Constant))): |
|
102 break |
|
103 else: |
|
104 return |
|
105 select.set_where(origrqlst.where.copy(select)) |
|
106 if not select.selection: |
|
107 # no selection, append one randomly |
|
108 select.append_selected(rel.children[0].copy(select)) |
|
109 return select |
|
110 |
79 |
111 |
80 class SSPlanner(object): |
112 class SSPlanner(object): |
81 """SingleSourcePlanner: build execution plan for rql queries |
113 """SingleSourcePlanner: build execution plan for rql queries |
82 |
114 |
83 optimized for single source repositories |
115 optimized for single source repositories |
142 if rschema.final or rschema.inlined: |
174 if rschema.final or rschema.inlined: |
143 rdefs[i] = (rtype, InsertRelationsStep.FINAL, value) |
175 rdefs[i] = (rtype, InsertRelationsStep.FINAL, value) |
144 else: |
176 else: |
145 rdefs[i] = (rtype, InsertRelationsStep.RELATION, value) |
177 rdefs[i] = (rtype, InsertRelationsStep.RELATION, value) |
146 step = InsertRelationsStep(plan, edef, rdefs) |
178 step = InsertRelationsStep(plan, edef, rdefs) |
147 if select.selection: |
179 select = _build_substep_query(select, rqlst) |
148 if rqlst.where is not None: |
180 if select is not None: |
149 select.set_where(rqlst.where.copy(select)) |
|
150 step.children += self._select_plan(plan, select, rqlst.solutions) |
181 step.children += self._select_plan(plan, select, rqlst.solutions) |
151 yield step |
182 yield step |
152 |
183 |
153 def build_delete_plan(self, plan, rqlst): |
184 def build_delete_plan(self, plan, rqlst): |
154 """get an execution plan from a DELETE RQL query""" |
185 """get an execution plan from a DELETE RQL query""" |
239 if rschema.final or rschema.inlined: |
270 if rschema.final or rschema.inlined: |
240 attributes.add(relation.r_type) |
271 attributes.add(relation.r_type) |
241 # the update step |
272 # the update step |
242 step = UpdateStep(plan, updatedefs, attributes) |
273 step = UpdateStep(plan, updatedefs, attributes) |
243 # when necessary add substep to fetch yet unknown values |
274 # when necessary add substep to fetch yet unknown values |
244 if select.selection: |
275 select = _build_substep_query(select, rqlst) |
245 if rqlst.where is not None: |
276 if select is not None: |
246 select.set_where(rqlst.where.copy(select)) |
|
247 # set distinct to avoid potential duplicate key error |
277 # set distinct to avoid potential duplicate key error |
248 select.distinct = True |
278 select.distinct = True |
249 step.children += self._select_plan(plan, select, rqlst.solutions) |
279 step.children += self._select_plan(plan, select, rqlst.solutions) |
250 return (step,) |
280 return (step,) |
251 |
281 |