optimize variable stinfo:
* uidrels/typerels sets become uidrel/typerel, and raise error if the rql
use multiple uid/type restriction for a variable (wasn't properly handled
anyway, should use IN)
* blocsimplification / optrelations / attrvars set are created only when
necessary
-> up to 5 less set per variable killed, should improve rql cache memory
foot print and somewhat speed-up annotation
--- a/__init__.py Wed Mar 24 18:05:18 2010 +0100
+++ b/__init__.py Wed Mar 24 18:05:19 2010 +0100
@@ -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,16 +166,13 @@
# 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]
+ stinfo['uidrel'] = None
rewritten = True
if vconsts:
select.stinfo['rewritten'][var.name] = vconsts
--- a/nodes.py Wed Mar 24 18:05:18 2010 +0100
+++ b/nodes.py Wed Mar 24 18:05:19 2010 +0100
@@ -836,33 +836,32 @@
# 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(),
- # 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,
- # 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,
})
+ 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]
- 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']:
--- a/stcheck.py Wed Mar 24 18:05:18 2010 +0100
+++ b/stcheck.py Wed Mar 24 18:05:19 2010 +0100
@@ -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,29 +479,42 @@
vref.unregister_reference()
newvref = VariableRef(newvar)
vref.parent.replace(vref, newvref)
+ stinfo = var.stinfo
# 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)
- 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:
- var.stinfo['attrvar'] = None
- var.stinfo['rhsrelations'].remove(rel)
+ stinfo['attrvar'] = None
+ stinfo['rhsrelations'].remove(rel)
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,10 +545,8 @@
# 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:
- lhsvar.stinfo['typerels'].add(relation)
+ lhsvar.stinfo['typerel'] = relation
return
if relation.optional is not None:
exists = relation.scope
@@ -539,20 +555,20 @@
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':
- lhsvar.stinfo['optrelations'].add(relation)
+ lhsvar.add_optional_relation(relation)
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)
- rhsvar.stinfo['blocsimplification'].add(relation)
+ bloc_simplification(rhsvar, relation)
if relation.optional == 'right':
- rhsvar.stinfo['optrelations'].add(relation)
+ rhsvar.add_optional_relation(relation)
elif relation.optional == 'both':
- rhsvar.stinfo['optrelations'].add(relation)
+ rhsvar.add_optional_relation(relation)
except AttributeError:
# may have been rewritten as well
pass
@@ -570,11 +586,11 @@
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:
- lhsvar.stinfo['blocsimplification'].add(relation)
+ bloc_simplification(lhsvar, relation)
for vref in rhs.get_nodes(VariableRef):
var = vref.variable
var.set_scope(scope)
@@ -586,8 +602,13 @@
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)
- 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):