[querier] fix eid relations handling in SET queries (closes #2797052)

_extract_eid_consts() implementation must consider arithmetic operators when trying to associate rql variables to specific eids.

authorAdrien Di Mascio <Adrien.DiMascio@logilab.fr>
changeset8d14c264152a
brancholdstable
phasedraft
hiddenyes
parent revision#dbffb6959564 server/source/native: fix wrong usage of .lstrip that produce garbled error messages (closes #2777641)
child revision<not specified>
files modified by this revision
server/ssplanner.py
server/test/unittest_querier.py
# HG changeset patch
# User Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
# Date 1365412190 -7200
# Mon Apr 08 11:09:50 2013 +0200
# Branch oldstable
# Node ID 8d14c264152ad42ac1bfb259e5f0ee6adfc013f8
# Parent dbffb6959564baed44c96b322e86da80f1858030
[querier] fix eid relations handling in SET queries (closes #2797052)

_extract_eid_consts() implementation must consider arithmetic operators
when trying to associate rql variables to specific eids.

diff --git a/server/ssplanner.py b/server/ssplanner.py
@@ -77,11 +77,16 @@
1      eidconsts = {}
2      neweids = session.transaction_data.get('neweids', ())
3      checkread = session.read_security
4      eschema = session.vreg.schema.eschema
5      for rel in rqlst.where.get_nodes(Relation):
6 -        if rel.r_type == 'eid' and not rel.neged(strict=True):
7 +        # only care for 'eid' relations ...
8 +        if (rel.r_type == 'eid'
9 +            # ... that are not part of a NOT clause ...
10 +            and not rel.neged(strict=True)
11 +            # ... and where eid is specified by '=' operator.
12 +            and rel.children[1].operator == '='):
13              lhs, rhs = rel.get_variable_parts()
14              if isinstance(rhs, Constant):
15                  eid = typed_eid(rhs.eval(plan.args))
16                  # check read permission here since it may not be done by
17                  # the generated select substep if not emited (eg nothing
diff --git a/server/test/unittest_querier.py b/server/test/unittest_querier.py
@@ -1515,7 +1515,30 @@
18              res = self.execute('Any X WHERE X has_text %(text)s', {'text': 'aff1'})
19              self.assertEqual(res.rows, [[aff1.eid]])
20              res = self.execute('Any X WHERE X has_text %(text)s', {'text': 'aff2'})
21              self.assertEqual(res.rows, [[aff2.eid]])
22 
23 +    def test_set_relations_eid(self):
24 +        req = self.request()
25 +        # create 3 email addresses
26 +        a1 = req.create_entity('EmailAddress', address=u'a1')
27 +        a2 = req.create_entity('EmailAddress', address=u'a2')
28 +        a3 = req.create_entity('EmailAddress', address=u'a3')
29 +        # SET relations using '>=' operator on eids
30 +        req.execute('SET U use_email A WHERE U login "admin", A eid >= %s' % a2.eid)
31 +        self.assertEqual(
32 +            [[a2.eid], [a3.eid]],
33 +            req.execute('Any A ORDERBY A WHERE U use_email A, U login "admin"').rows)
34 +        # DELETE
35 +        req.execute('DELETE U use_email A WHERE U login "admin", A eid > %s' % a2.eid)
36 +        self.assertEqual(
37 +            [[a2.eid]],
38 +            req.execute('Any A ORDERBY A WHERE U use_email A, U login "admin"').rows)
39 +        req.execute('DELETE U use_email A WHERE U login "admin"')
40 +        # SET relations using '<' operator on eids
41 +        req.execute('SET U use_email A WHERE U login "admin", A eid < %s' % a2.eid)
42 +        self.assertEqual(
43 +            [[a1.eid]],
44 +            req.execute('Any A ORDERBY A WHERE U use_email A, U login "admin"').rows)
45 +
46  if __name__ == '__main__':
47      unittest_main()