diff --git a/stcheck.py b/stcheck.py index 27e3b01795e58637490a13a6c391079d808a259a_c3RjaGVjay5weQ==..fb5b388f7436c006a13d2deeed15245f707a61f1_c3RjaGVjay5weQ== 100644 --- a/stcheck.py +++ b/stcheck.py @@ -412,6 +412,13 @@ for var in node.defined_vars.itervalues(): if not var.stinfo['relations'] and var.stinfo['typerels'] and not var.stinfo['selected']: raise BadRQLQuery('unbound variable %s (%s)' % (var.name, var.stmt.root)) + if len(var.stinfo['uidrels']) > 1: + uidrels = iter(var.stinfo['uidrels']) + val = getattr(uidrels.next().get_variable_parts()[1], 'value', object()) + for uidrel in uidrels: + if getattr(uidrel.get_variable_parts()[1], 'value', None) != val: + # XXX should check OR branch and check simplify in that case as well + raise BadRQLQuery('conflicting eid values for %s' % var.name) def rewrite_shared_optional(self, exists, var): """if variable is shared across multiple scopes, need some tree diff --git a/test/unittest_stcheck.py b/test/unittest_stcheck.py index 27e3b01795e58637490a13a6c391079d808a259a_dGVzdC91bml0dGVzdF9zdGNoZWNrLnB5..fb5b388f7436c006a13d2deeed15245f707a61f1_dGVzdC91bml0dGVzdF9zdGNoZWNrLnB5 100644 --- a/test/unittest_stcheck.py +++ b/test/unittest_stcheck.py @@ -1,6 +1,6 @@ from logilab.common.testlib import TestCase, unittest_main from unittest_analyze import DummySchema from rql import RQLHelper, BadRQLQuery, stmts, nodes - + BAD_QUERIES = ( 'Any X, Y GROUPBY X', @@ -5,5 +5,5 @@ BAD_QUERIES = ( 'Any X, Y GROUPBY X', - + # this is now a valid query #'DISTINCT Any X WHERE X work_for Y ORDERBY Y', @@ -8,4 +8,4 @@ # this is now a valid query #'DISTINCT Any X WHERE X work_for Y ORDERBY Y', - + 'Any X WHERE X name Person', @@ -11,5 +11,5 @@ 'Any X WHERE X name Person', - + 'Any X WHERE X name nofunction(Y)', 'Any X WHERE X name nofunction(Y)', @@ -13,7 +13,7 @@ 'Any X WHERE X name nofunction(Y)', 'Any X WHERE X name nofunction(Y)', - + 'Any Y WHERE X name "toto"', 'Any X WHERE X noattr "toto"', @@ -17,5 +17,5 @@ 'Any Y WHERE X name "toto"', 'Any X WHERE X noattr "toto"', - + 'Any X WHERE X is NonExistant', @@ -21,5 +21,5 @@ 'Any X WHERE X is NonExistant', - + 'Any UPPER(Y) WHERE X name "toto"', 'Any C ORDERBY N where C located P, P eid %(x)s', #15066 @@ -35,7 +35,9 @@ # BAD QUERY cant sort on y 'DISTINCT Any X ORDERBY Y WHERE B work_for X, B name Y', - + + "Any X WHERE X eid 0, X eid 1" + ) OK_QUERIES = ( @@ -51,9 +53,9 @@ 'DISTINCT Any B ORDERBY Y WHERE B work_for X, X name Y', # 'DISTINCT Any X ORDERBY SN WHERE X in_state S, S name SN', - - + + ) class CheckClassTest(TestCase): """check wrong queries are correctly detected""" @@ -56,9 +58,9 @@ ) class CheckClassTest(TestCase): """check wrong queries are correctly detected""" - + def setUp(self): helper = RQLHelper(DummySchema(), None, {'eid': 'uid'}) self.parse = helper.parse self.simplify = helper.simplify @@ -61,11 +63,11 @@ def setUp(self): helper = RQLHelper(DummySchema(), None, {'eid': 'uid'}) self.parse = helper.parse self.simplify = helper.simplify - + def _test(self, rql): try: self.assertRaises(BadRQLQuery, self.parse, rql) except: print rql raise @@ -66,10 +68,10 @@ def _test(self, rql): try: self.assertRaises(BadRQLQuery, self.parse, rql) except: print rql raise - + def test_raise(self): for rql in BAD_QUERIES: yield self._test, rql @@ -73,7 +75,7 @@ def test_raise(self): for rql in BAD_QUERIES: yield self._test, rql - + def test_ok(self): for rql in OK_QUERIES: yield self.parse, rql @@ -77,8 +79,8 @@ def test_ok(self): for rql in OK_QUERIES: yield self.parse, rql - + def _test_rewrite(self, rql, expected): rqlst = self.parse(rql) self.simplify(rqlst) self.assertEquals(rqlst.as_string(), expected) @@ -81,8 +83,8 @@ def _test_rewrite(self, rql, expected): rqlst = self.parse(rql) self.simplify(rqlst) self.assertEquals(rqlst.as_string(), expected) - + def test_rewrite(self): for rql, expected in ( ('Person X', @@ -123,7 +125,7 @@ ('Any X WHERE X eid > 12', 'Any X WHERE X eid > 12'), - + ('Any X WHERE X eid 12, X connait P?, X work_for Y', 'Any X WHERE X eid 12, X connait P?, X work_for Y'), ('Any X WHERE X eid 12, P? connait X', @@ -136,7 +138,7 @@ ('Any X WHERE X eid 12, EXISTS(X name "hop" OR X work_for Y?)', "Any 12 WHERE EXISTS((A name 'hop') OR (A work_for Y?), 12 identity A)"), - + ('(Any X WHERE X eid 12) UNION (Any X ORDERBY X WHERE X eid 13)', '(Any 12) UNION (Any 13)'), @@ -166,8 +168,8 @@ ('VC', 'VF'): 'connait', ('VC', 'VCD'): 'creation_date'}) self.assertEquals(rqlst.children[0].aggregated, set(('VC',))) - - + + ## def test_rewriten_as_string(self): ## rqlst = self.parse('Any X WHERE X eid 12') ## self.assertEquals(rqlst.as_string(), 'Any X WHERE X eid 12') @@ -176,7 +178,7 @@ ## self.assertEquals(rqlst.as_string(), 'Any X WHERE X eid 12') class CopyTest(TestCase): - + def setUp(self): helper = RQLHelper(DummySchema(), None, {'eid': 'uid'}) self.parse = helper.parse @@ -191,7 +193,7 @@ exists = copy.get_nodes(nodes.Exists)[0] self.failUnless(exists.children[0].parent is exists) self.failUnless(exists.parent) - + def test_copy_internals(self): root = self.parse('Any X,U WHERE C owned_by U, NOT X owned_by U, X eid 1, C eid 2') self.simplify(root) @@ -210,7 +212,7 @@ class AnnotateTest(TestCase): - + def setUp(self): helper = RQLHelper(DummySchema(), None, {'eid': 'uid'}) self.parse = helper.parse @@ -241,6 +243,6 @@ C = rqlst.with_[0].query.children[0].defined_vars['C'] self.failUnless(C.scope is rqlst.with_[0].query.children[0], C.scope) self.assertEquals(len(C.stinfo['relations']), 2) - + if __name__ == '__main__': unittest_main()