def _compute_relation_steps(self, plan, rqlst, to_select): """handle the selection of relations for an insert query""" eidconsts = _extract_eid_consts(plan, rqlst) for edef, rdefs in to_select.items(): # create a select rql st to fetch needed data select = Select() eschema = edef.entity.e_schema for i, (rtype, term, reverse) in enumerate(rdefs): if getattr(term, 'variable', None) in eidconsts: value = eidconsts[term.variable] else: select.append_selected(term.copy(select)) value = _FROM_SUBSTEP if reverse: rdefs[i] = (rtype, InsertRelationsStep.REVERSE_RELATION, value) else: rschema = eschema.subjrels[rtype] if rschema.final or rschema.inlined: rdefs[i] = (rtype, InsertRelationsStep.FINAL, value) else: rdefs[i] = (rtype, InsertRelationsStep.RELATION, value) step = InsertRelationsStep(plan, edef, rdefs) select = _build_substep_query(select, rqlst) if select is not None: step.children += self._select_plan(plan, select, rqlst.solutions) yield step
def build_set_plan(self, plan, rqlst): """get an execution plan from an SET RQL query""" getrschema = self.schema.rschema select = Select() # potential substep query selectedidx = {} # local state updatedefs = [] # definition of update attributes/relations selidx = residx = 0 # substep selection / resulting rset indexes # search for eid const in the WHERE clause eidconsts = _extract_eid_consts(plan, rqlst) # build `updatedefs` describing things to update and add necessary # variables to the substep selection for i, relation in enumerate(rqlst.main_relations): if relation.r_type in VIRTUAL_RTYPES: raise QueryError('can not assign to %r relation' % relation.r_type) lhs, rhs = relation.get_variable_parts() lhskey = lhs.as_string() if lhskey not in selectedidx: if lhs.variable in eidconsts: eid = eidconsts[lhs.variable] lhsinfo = (_CONSTANT, eid, residx) else: select.append_selected(lhs.copy(select)) lhsinfo = (_FROM_SUBSTEP, selidx, residx) selidx += 1 residx += 1 selectedidx[lhskey] = lhsinfo else: lhsinfo = selectedidx[lhskey][:-1] + (None, ) rhskey = rhs.as_string() if rhskey not in selectedidx: if isinstance(rhs, Constant): rhsinfo = (_CONSTANT, rhs.eval(plan.args), residx) elif getattr(rhs, 'variable', None) in eidconsts: eid = eidconsts[rhs.variable] rhsinfo = (_CONSTANT, eid, residx) else: select.append_selected(rhs.copy(select)) rhsinfo = (_FROM_SUBSTEP, selidx, residx) selidx += 1 residx += 1 selectedidx[rhskey] = rhsinfo else: rhsinfo = selectedidx[rhskey][:-1] + (None, ) rschema = getrschema(relation.r_type) updatedefs.append((lhsinfo, rhsinfo, rschema)) # the update step step = UpdateStep(plan, updatedefs) # when necessary add substep to fetch yet unknown values select = _build_substep_query(select, rqlst) if select is not None: # set distinct to avoid potential duplicate key error select.distinct = True step.children += self._select_plan(plan, select, rqlst.solutions) return (step, )
def _sel_relation_steps(self, plan, rqlst, relation): """handle the selection of relations for a delete query""" select = Select() lhs, rhs = relation.get_variable_parts() select.append_selected(lhs.copy(select)) select.append_selected(rhs.copy(select)) select.set_where(relation.copy(select)) if rqlst.where is not None: select.add_restriction(rqlst.where.copy(select)) if getattr(rqlst, 'having', None): select.set_having([x.copy(select) for x in rqlst.having]) return self._select_plan(plan, select, rqlst.solutions)
def _sel_variable_step(self, plan, rqlst, etype, varref): """handle the selection of variables for a delete query""" select = Select() varref = varref.copy(select) select.defined_vars = {varref.name: varref.variable} select.append_selected(varref) if rqlst.where is not None: select.set_where(rqlst.where.copy(select)) if getattr(rqlst, 'having', None): select.set_having([x.copy(select) for x in rqlst.having]) if etype != 'Any': select.add_type_restriction(varref.variable, etype) return self._select_plan(plan, select, rqlst.solutions)