closes #71157: bad analyze when using functions
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Wed, 20 Jul 2011 17:11:06 +0200
changeset 645 bc901a7460d1
parent 644 3142a4184677
child 646 e1cc9656bb4c
child 651 2a267149fee6
closes #71157: bad analyze when using functions
ChangeLog
analyze.py
test/unittest_analyze.py
--- a/ChangeLog	Tue Jul 19 18:15:17 2011 +0200
+++ b/ChangeLog	Wed Jul 20 17:11:06 2011 +0200
@@ -13,6 +13,8 @@
     * #71132: column alias scope should be handled as variable scope, not bound
       to subquery
 
+    * #71157: bad analyze when using functions
+
     * Select.replace must properly reset old node's parent attribute
 
     * new undo_modification context manager on select nodes
--- a/analyze.py	Tue Jul 19 18:15:17 2011 +0200
+++ b/analyze.py	Wed Jul 20 17:11:06 2011 +0200
@@ -493,45 +493,33 @@
             if not isinstance(lhs, nodes.VariableRef) or rhs.type is None:
                 return True
             self._extract_constraint(constraints, lhs.name, rhs, rschema.subjects)
-        else:
-            if not isinstance(lhs, nodes.VariableRef):
-                # XXX: check relation is valid
-                return True
+        elif not isinstance(lhs, nodes.VariableRef):
+            # XXX: check relation is valid
+            return True
+        elif isinstance(rhs, nodes.VariableRef):
             lhsvar = lhs.name
-            rhsvars = []
-            samevar = False
-            if not isinstance(rhs, nodes.MathExpression):
-                # rhs type is the result of the math expression, not of
-                # individual variables, so don't add constraints on rhs
-                # variables
-                for v in rhs.iget_nodes(nodes.VariableRef):
-                    if v.name == lhsvar:
-                        samevar = True
-                    else:
-                        rhsvars.append(v.name)
+            rhsvar = rhs.name
             lhsdomain = constraints.domains[lhsvar]
-            if rhsvars:
-                s2 = '=='.join(rhsvars)
-                # filter according to domain necessary for column aliases
-                rhsdomain = constraints.domains[rhsvars[0]]
-                res = []
-                for fromtype, totypes in rschema.associations():
-                    if not fromtype in lhsdomain:
-                        continue
-                    ptypes = [str(t) for t in totypes if t in rhsdomain]
-                    res.append( [ ( [lhsvar], [str(fromtype)]), (rhsvars, ptypes) ] )
-                constraints.or_and( res )
-            else:
-                ptypes = [str(subj) for subj in rschema.subjects()
-                          if subj in lhsdomain]
-                constraints.var_has_types( lhsvar, ptypes )
-            if samevar:
-                res = []
-                for fromtype, totypes in rschema.associations():
-                    if not (fromtype in totypes and fromtype in lhsdomain):
-                        continue
-                    res.append(str(fromtype))
+            # filter according to domain necessary for column aliases
+            rhsdomain = constraints.domains[rhsvar]
+            res = []
+            for fromtype, totypes in rschema.associations():
+                if not fromtype in lhsdomain:
+                    continue
+                ptypes = [str(t) for t in totypes if t in rhsdomain]
+                res.append( [ ([lhsvar], [str(fromtype)]),
+                              ([rhsvar], ptypes) ] )
+            constraints.or_and(res)
+            if rhsvar == lhsvar:
+                res = [str(fromtype) for fromtype, totypes in rschema.associations()
+                       if (fromtype in totypes and fromtype in lhsdomain)]
                 constraints.var_has_types( lhsvar, res )
+        else:
+            # XXX consider rhs.get_type?
+            lhsdomain = constraints.domains[lhs.name]
+            ptypes = [str(subj) for subj in rschema.subjects()
+                      if subj in lhsdomain]
+            constraints.var_has_types( lhs.name, ptypes )
         return True
 
     def visit_type_restriction(self, relation, constraints):
--- a/test/unittest_analyze.py	Tue Jul 19 18:15:17 2011 +0200
+++ b/test/unittest_analyze.py	Wed Jul 20 17:11:06 2011 +0200
@@ -531,7 +531,7 @@
                                 {'P': 'Student', 'S': 'Company', 'N': 'Int'}])
 
 
-    def test_nongrer_not_u_ownedby_u(self):
+    def test_nonregr_not_u_ownedby_u(self):
         node = self.helper.parse('Any U WHERE NOT U owned_by U')
         self.helper.compute_solutions(node, debug=DEBUG)
         sols = sorted(node.children[0].solutions)