diff --git a/__init__.py b/__init__.py index ce3274a74fbafebbdf24bee46fac77a5b91195b5_X19pbml0X18ucHk=..9661f74aed0daf5669ea51469814ccb508e355ff_X19pbml0X18ucHk= 100644 --- a/__init__.py +++ b/__init__.py @@ -131,9 +131,8 @@ rewritten = False for var in select.defined_vars.values(): stinfo = var.stinfo - if stinfo['constnode'] and not stinfo['blocsimplification']: - #assert len(stinfo['uidrels']) == 1, var - uidrel = stinfo['uidrels'].pop() + if stinfo['constnode'] and not stinfo.get('blocsimplification'): + uidrel = stinfo['uidrel'] var = uidrel.children[0].variable vconsts = [] rhs = uidrel.children[1].children[0] @@ -167,13 +166,9 @@ # drop this relation rel.parent.remove(rel) elif rel.is_types_restriction(): - stinfo['typerels'].remove(rel) - rel.parent.remove(rel) - elif rel in stinfo['uidrels']: - # XXX check equivalence not necessary else we wouldn't be here right? - stinfo['uidrels'].remove(rel) + stinfo['typerel'] = None rel.parent.remove(rel) else: rhs = copy_uid_node(select, rhs, vconsts) vref.parent.replace(vref, rhs) del select.defined_vars[var.name] @@ -175,8 +170,9 @@ rel.parent.remove(rel) else: rhs = copy_uid_node(select, rhs, vconsts) vref.parent.replace(vref, rhs) del select.defined_vars[var.name] + stinfo['uidrel'] = None rewritten = True if vconsts: select.stinfo['rewritten'][var.name] = vconsts diff --git a/nodes.py b/nodes.py index ce3274a74fbafebbdf24bee46fac77a5b91195b5_bm9kZXMucHk=..9661f74aed0daf5669ea51469814ccb508e355ff_bm9kZXMucHk= 100644 --- a/nodes.py +++ b/nodes.py @@ -836,14 +836,5 @@ # relations where this variable is used on the lhs/rhs 'relations': set(), 'rhsrelations': set(), - 'optrelations': set(), - # empty if this variable may be simplified (eg not used in optional - # relations and no final relations where this variable is used on - # the lhs) - 'blocsimplification': set(), - # type relations (e.g. "is") where this variable is used on the lhs - 'typerels': set(), - # uid relations (e.g. "eid") where this variable is used on the lhs - 'uidrels': set(), # selection indexes if any 'selected': set(), @@ -848,5 +839,10 @@ # selection indexes if any 'selected': set(), - # if this variable is an attribute variable (ie final entity), - # link to the (prefered) attribute owner variable + # type restriction (e.g. "is" / "is_instance_of") where this + # variable is used on the lhs + 'typerel': None, + # uid relations (e.g. "eid") where this variable is used on the lhs + 'uidrel': None, + # if this variable is an attribute variable (ie final entity), link + # to the (prefered) attribute owner variable 'attrvar': None, @@ -852,8 +848,5 @@ 'attrvar': None, - # set of couple (lhs variable name, relation name) where this - # attribute variable is used - 'attrvars': set(), # constant node linked to an uid variable if any 'constnode': None, }) @@ -856,8 +849,14 @@ # constant node linked to an uid variable if any 'constnode': None, }) + def add_optional_relation(self, relation): + try: + self.stinfo['optrelations'].add(relation) + except KeyError: + self.stinfo['optrelations'] = set((relation,)) + def get_type(self, solution=None, kwargs=None): """return entity type of this object, 'Any' if not found""" if solution: return solution[self.name] @@ -860,9 +859,9 @@ def get_type(self, solution=None, kwargs=None): """return entity type of this object, 'Any' if not found""" if solution: return solution[self.name] - for rel in self.stinfo['typerels']: - return str(rel.children[1].children[0].value) + if self.stinfo['typerel']: + return str(self.stinfo['typerel'].children[1].children[0].value) schema = self.schema if schema is not None: for rel in self.stinfo['rhsrelations']: diff --git a/stcheck.py b/stcheck.py index ce3274a74fbafebbdf24bee46fac77a5b91195b5_c3RjaGVjay5weQ==..9661f74aed0daf5669ea51469814ccb508e355ff_c3RjaGVjay5weQ== 100644 --- a/stcheck.py +++ b/stcheck.py @@ -24,6 +24,12 @@ except KeyError: return subvarname + str(id(select)) +def bloc_simplification(variable, term): + try: + variable.stinfo['blocsimplification'].add(term) + except KeyError: + variable.stinfo['blocsimplification'] = set((term,)) + class GoTo(Exception): """Exception used to control the visit of the tree.""" @@ -407,7 +413,6 @@ pass - class RQLSTAnnotator(object): """Annotate RQL syntax tree to ease further code generation from it. @@ -459,7 +464,7 @@ # if there is a having clause, bloc simplification of variables used in GROUPBY for term in node.groupby: for vref in term.get_nodes(VariableRef): - vref.variable.stinfo['blocsimplification'].add(term) + bloc_simplification(vref.variable, term) def rewrite_shared_optional(self, exists, var): """if variable is shared across multiple scopes, need some tree @@ -474,5 +479,6 @@ vref.unregister_reference() newvref = VariableRef(newvar) vref.parent.replace(vref, newvref) + stinfo = var.stinfo # update stinfo structure which may have already been # partially processed @@ -477,8 +483,8 @@ # update stinfo structure which may have already been # partially processed - if rel in var.stinfo['rhsrelations']: + if rel in stinfo['rhsrelations']: lhs, rhs = rel.get_parts() if vref is rhs.children[0] and \ self.schema.rschema(rel.r_type).final: update_attrvars(newvar, rel, lhs) lhsvar = getattr(lhs, 'variable', None) @@ -480,10 +486,10 @@ lhs, rhs = rel.get_parts() if vref is rhs.children[0] and \ self.schema.rschema(rel.r_type).final: update_attrvars(newvar, rel, lhs) lhsvar = getattr(lhs, 'variable', None) - var.stinfo['attrvars'].remove( (lhsvar, rel.r_type) ) - if var.stinfo['attrvar'] is lhsvar: - if var.stinfo['attrvars']: - var.stinfo['attrvar'] = iter(var.stinfo['attrvars']).next() + stinfo['attrvars'].remove( (lhsvar, rel.r_type) ) + if stinfo['attrvar'] is lhsvar: + if stinfo['attrvars']: + stinfo['attrvar'] = iter(stinfo['attrvars']).next() else: @@ -489,4 +495,4 @@ else: - var.stinfo['attrvar'] = None - var.stinfo['rhsrelations'].remove(rel) + stinfo['attrvar'] = None + stinfo['rhsrelations'].remove(rel) newvar.stinfo['rhsrelations'].add(rel) @@ -492,11 +498,23 @@ newvar.stinfo['rhsrelations'].add(rel) - for stinfokey in ('blocsimplification','typerels', 'uidrels', - 'relations', 'optrelations'): - try: - var.stinfo[stinfokey].remove(rel) - newvar.stinfo[stinfokey].add(rel) - except KeyError: - continue + try: + stinfo['relations'].remove(rel) + newvar.stinfo['relations'].add(rel) + except KeyError: + pass + try: + stinfo['optrelations'].remove(rel) + newvar.add_optional_relation(rel) + except KeyError: + pass + try: + stinfo['blocsimplification'].remove(rel) + bloc_simplification(newvar, rel) + except KeyError: + pass + if stinfo['uidrel'] is rel: + newvar.stinfo['uidrel'] = rel + if stinfo['typerel'] is rel: + newvar.stinfo['typerel'] = rel # shared references newvar.stinfo['constnode'] = var.stinfo['constnode'] if newvar.stmt.solutions: # solutions already computed @@ -527,6 +545,4 @@ # may be a constant once rqlst has been simplified lhsvar = getattr(lhs, 'variable', None) if relation.is_types_restriction(): - #assert rhs.operator == '=' - #assert not relation.optional if lhsvar is not None: @@ -532,5 +548,5 @@ if lhsvar is not None: - lhsvar.stinfo['typerels'].add(relation) + lhsvar.stinfo['typerel'] = relation return if relation.optional is not None: exists = relation.scope @@ -539,5 +555,5 @@ if lhsvar is not None: if exists is not None and lhsvar.scope is lhsvar.stmt: lhsvar = self.rewrite_shared_optional(exists, lhsvar) - lhsvar.stinfo['blocsimplification'].add(relation) + bloc_simplification(lhsvar, relation) if relation.optional == 'both': @@ -543,3 +559,3 @@ if relation.optional == 'both': - lhsvar.stinfo['optrelations'].add(relation) + lhsvar.add_optional_relation(relation) elif relation.optional == 'left': @@ -545,6 +561,6 @@ elif relation.optional == 'left': - lhsvar.stinfo['optrelations'].add(relation) + lhsvar.add_optional_relation(relation) try: rhsvar = rhs.children[0].variable if exists is not None and rhsvar.scope is rhsvar.stmt: rhsvar = self.rewrite_shared_optional(exists, rhsvar) @@ -547,6 +563,6 @@ try: rhsvar = rhs.children[0].variable if exists is not None and rhsvar.scope is rhsvar.stmt: rhsvar = self.rewrite_shared_optional(exists, rhsvar) - rhsvar.stinfo['blocsimplification'].add(relation) + bloc_simplification(rhsvar, relation) if relation.optional == 'right': @@ -552,3 +568,3 @@ if relation.optional == 'right': - rhsvar.stinfo['optrelations'].add(relation) + rhsvar.add_optional_relation(relation) elif relation.optional == 'both': @@ -554,5 +570,5 @@ elif relation.optional == 'both': - rhsvar.stinfo['optrelations'].add(relation) + rhsvar.add_optional_relation(relation) except AttributeError: # may have been rewritten as well pass @@ -570,7 +586,7 @@ isinstance(relation.parent, Not)): if isinstance(constnode, Constant): lhsvar.stinfo['constnode'] = constnode - lhsvar.stinfo.setdefault(key, set()).add(relation) + lhsvar.stinfo['uidrel'] = relation else: lhsvar.stinfo.setdefault(key, set()).add(relation) elif rschema.final or rschema.inlined: @@ -574,7 +590,7 @@ else: lhsvar.stinfo.setdefault(key, set()).add(relation) elif rschema.final or rschema.inlined: - lhsvar.stinfo['blocsimplification'].add(relation) + bloc_simplification(lhsvar, relation) for vref in rhs.get_nodes(VariableRef): var = vref.variable var.set_scope(scope) @@ -586,4 +602,6 @@ def update_attrvars(var, relation, lhs): + # stinfo['attrvars'] is set of couple (lhs variable name, relation name) + # where the `var` attribute variable is used lhsvar = getattr(lhs, 'variable', None) @@ -589,5 +607,8 @@ lhsvar = getattr(lhs, 'variable', None) - var.stinfo['attrvars'].add( (lhsvar, relation.r_type) ) + try: + var.stinfo['attrvars'].add( (lhsvar, relation.r_type) ) + except KeyError: + var.stinfo['attrvars'] = set([(lhsvar, relation.r_type)]) # give priority to variable which is not in an EXISTS as # "main" attribute variable if var.stinfo['attrvar'] is None or not isinstance(relation.scope, Exists):