[computed attribute] ensure attribute's formula apply only to the correct type. Closes #4901163
--- a/hooks/synccomputed.py Mon Feb 02 22:05:00 2015 +0100
+++ b/hooks/synccomputed.py Mon Feb 02 23:17:15 2015 +0100
@@ -161,6 +161,8 @@
# expected to have been set by finalize_computed_attributes
select = rdef.formula_select
for rel_node in select.get_nodes(nodes.Relation):
+ if rel_node.is_types_restriction():
+ continue
rschema = schema.rschema(rel_node.r_type)
lhs, rhs = rel_node.get_variable_parts()
for sol in select.solutions:
--- a/hooks/test/data-computed/schema.py Mon Feb 02 22:05:00 2015 +0100
+++ b/hooks/test/data-computed/schema.py Mon Feb 02 23:17:15 2015 +0100
@@ -29,3 +29,18 @@
class Societe(EntityType):
nom = String()
salaire_total = Int(formula='Any SUM(SA) GROUPBY X WHERE P travaille X, P salaire SA')
+
+
+class Agent(EntityType):
+ asalae_id = String(formula='Any E WHERE M mirror_of X, M extid E')
+
+class MirrorEntity(EntityType):
+ extid = String(required=True, unique=True,
+ description=_('external identifier of the object'))
+
+
+class mirror_of(RelationDefinition):
+ subject = 'MirrorEntity'
+ object = ('Agent', 'Societe')
+ cardinality = '?*'
+ inlined = True
--- a/hooks/test/unittest_synccomputed.py Mon Feb 02 22:05:00 2015 +0100
+++ b/hooks/test/unittest_synccomputed.py Mon Feb 02 23:17:15 2015 +0100
@@ -134,6 +134,13 @@
self.assertEqual(rset[0][0], 2014 - 1990)
+ def test_recompute_on_ambiguous_relation(self):
+ # check we don't end up with TypeResolverException as in #4901163
+ with self.admin_access.client_cnx() as cnx:
+ societe = cnx.create_entity('Societe', nom=u'Foo')
+ cnx.create_entity('MirrorEntity', mirror_of=societe, extid=u'1')
+ cnx.commit()
+
if __name__ == '__main__':
from logilab.common.testlib import unittest_main
unittest_main()
--- a/schema.py Mon Feb 02 22:05:00 2015 +0100
+++ b/schema.py Mon Feb 02 23:17:15 2015 +0100
@@ -1072,6 +1072,7 @@
for rdef in self.iter_computed_attributes():
rqlst = parse(rdef.formula)
select = rqlst.children[0]
+ select.add_type_restriction(select.defined_vars['X'], str(rdef.subject))
analyzer.visit(select)
_check_valid_formula(rdef, rqlst)
rdef.formula_select = select # avoid later recomputation
--- a/test/unittest_schema.py Mon Feb 02 22:05:00 2015 +0100
+++ b/test/unittest_schema.py Mon Feb 02 23:17:15 2015 +0100
@@ -299,6 +299,10 @@
'P works_for X, P salary SA')
good_schema = build_schema_from_namespace(vars().items())
+ # ensure 'X is Company' is added to the rqlst to avoid ambiguities, see #4901163
+ self.assertEqual(str(good_schema['Company'].rdef('total_salary').formula_select),
+ 'Any SUM(SA) GROUPBY X WHERE P works_for X, P salary SA, X is Company')
+
class Company(EntityType):
total_salary = String(formula='Any SUM(SA) GROUPBY X WHERE '
'P works_for X, P salary SA')