server/test/unittest_msplanner.py
changeset 6427 c8a5ac2d1eaa
parent 6366 1806148d6ce8
child 6631 26c303c3f1aa
equal deleted inserted replaced
6426:541659c39f6a 6427:c8a5ac2d1eaa
    16 # You should have received a copy of the GNU Lesser General Public License along
    16 # You should have received a copy of the GNU Lesser General Public License along
    17 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
    17 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
    18 
    18 
    19 from logilab.common.decorators import clear_cache
    19 from logilab.common.decorators import clear_cache
    20 
    20 
       
    21 from rql import BadRQLQuery
       
    22 
    21 from cubicweb.devtools import init_test_database
    23 from cubicweb.devtools import init_test_database
    22 from cubicweb.devtools.repotest import BasePlannerTC, test_plan
    24 from cubicweb.devtools.repotest import BasePlannerTC, test_plan
    23 
    25 
    24 class _SetGenerator(object):
    26 class _SetGenerator(object):
    25     """singleton to easily create set using "s[0]" or "s[0,1,2]" for instance
    27     """singleton to easily create set using "s[0]" or "s[0,1,2]" for instance
    57 
    59 
    58 X_ALL_SOLS = sorted([{'X': 'Affaire'}, {'X': 'BaseTransition'}, {'X': 'Basket'},
    60 X_ALL_SOLS = sorted([{'X': 'Affaire'}, {'X': 'BaseTransition'}, {'X': 'Basket'},
    59                      {'X': 'Bookmark'}, {'X': 'CWAttribute'}, {'X': 'CWCache'},
    61                      {'X': 'Bookmark'}, {'X': 'CWAttribute'}, {'X': 'CWCache'},
    60                      {'X': 'CWConstraint'}, {'X': 'CWConstraintType'}, {'X': 'CWEType'},
    62                      {'X': 'CWConstraint'}, {'X': 'CWConstraintType'}, {'X': 'CWEType'},
    61                      {'X': 'CWGroup'}, {'X': 'CWPermission'}, {'X': 'CWProperty'},
    63                      {'X': 'CWGroup'}, {'X': 'CWPermission'}, {'X': 'CWProperty'},
    62                      {'X': 'CWRType'}, {'X': 'CWRelation'}, {'X': 'CWUser'},
    64                      {'X': 'CWRType'}, {'X': 'CWRelation'},
    63                      {'X': 'CWUniqueTogetherConstraint'},
    65                      {'X': 'CWSource'}, {'X': 'CWSourceHostConfig'},
       
    66                      {'X': 'CWUser'}, {'X': 'CWUniqueTogetherConstraint'},
    64                      {'X': 'Card'}, {'X': 'Comment'}, {'X': 'Division'},
    67                      {'X': 'Card'}, {'X': 'Comment'}, {'X': 'Division'},
    65                      {'X': 'Email'}, {'X': 'EmailAddress'}, {'X': 'EmailPart'},
    68                      {'X': 'Email'}, {'X': 'EmailAddress'}, {'X': 'EmailPart'},
    66                      {'X': 'EmailThread'}, {'X': 'ExternalUri'}, {'X': 'File'},
    69                      {'X': 'EmailThread'}, {'X': 'ExternalUri'}, {'X': 'File'},
    67                      {'X': 'Folder'}, {'X': 'Note'},
    70                      {'X': 'Folder'}, {'X': 'Note'},
    68                      {'X': 'Personne'}, {'X': 'RQLExpression'}, {'X': 'Societe'},
    71                      {'X': 'Personne'}, {'X': 'RQLExpression'}, {'X': 'Societe'},
   535                      [('Any X,AA WHERE X modification_date AA, X is CWUser',
   538                      [('Any X,AA WHERE X modification_date AA, X is CWUser',
   536                        [{'AA': 'Datetime', 'X': 'CWUser'}])],
   539                        [{'AA': 'Datetime', 'X': 'CWUser'}])],
   537                      [self.ldap, self.system], None,
   540                      [self.ldap, self.system], None,
   538                      {'AA': 'table0.C1', 'X': 'table0.C0', 'X.modification_date': 'table0.C1'}, []),
   541                      {'AA': 'table0.C1', 'X': 'table0.C0', 'X.modification_date': 'table0.C1'}, []),
   539                     ('OneFetchStep',
   542                     ('OneFetchStep',
   540                      [('Any X,AA ORDERBY AA WHERE 5 owned_by X, X modification_date AA, X is CWUser',
   543                      [('Any X,AA ORDERBY AA WHERE %s owned_by X, X modification_date AA, X is CWUser' % ueid,
   541                        [{'AA': 'Datetime', 'X': 'CWUser'}])],
   544                        [{'AA': 'Datetime', 'X': 'CWUser'}])],
   542                      None, None, [self.system],
   545                      None, None, [self.system],
   543                      {'AA': 'table0.C1', 'X': 'table0.C0', 'X.modification_date': 'table0.C1'}, []),
   546                      {'AA': 'table0.C1', 'X': 'table0.C0', 'X.modification_date': 'table0.C1'}, []),
   544                     ],
   547                     ],
   545                    {'x': ueid})
   548                    {'x': ueid})
   685                     ])
   688                     ])
   686 
   689 
   687     def test_complex_optional(self):
   690     def test_complex_optional(self):
   688         ueid = self.session.user.eid
   691         ueid = self.session.user.eid
   689         self._test('Any U WHERE WF wf_info_for X, X eid %(x)s, WF owned_by U?, WF from_state FS',
   692         self._test('Any U WHERE WF wf_info_for X, X eid %(x)s, WF owned_by U?, WF from_state FS',
   690                    [('OneFetchStep', [('Any U WHERE WF wf_info_for 5, WF owned_by U?, WF from_state FS',
   693                    [('OneFetchStep', [('Any U WHERE WF wf_info_for %s, WF owned_by U?, WF from_state FS' % ueid,
   691                                        [{'WF': 'TrInfo', 'FS': 'State', 'U': 'CWUser'}])],
   694                                        [{'WF': 'TrInfo', 'FS': 'State', 'U': 'CWUser'}])],
   692                      None, None, [self.system], {}, [])],
   695                      None, None, [self.system], {}, [])],
   693                    {'x': ueid})
   696                    {'x': ueid})
   694 
   697 
   695     def test_complex_optional(self):
   698     def test_complex_optional(self):
   696         ueid = self.session.user.eid
   699         ueid = self.session.user.eid
   697         self._test('Any U WHERE WF wf_info_for X, X eid %(x)s, WF owned_by U?, WF from_state FS',
   700         self._test('Any U WHERE WF wf_info_for X, X eid %(x)s, WF owned_by U?, WF from_state FS',
   698                    [('OneFetchStep', [('Any U WHERE WF wf_info_for 5, WF owned_by U?, WF from_state FS',
   701                    [('OneFetchStep', [('Any U WHERE WF wf_info_for %s, WF owned_by U?, WF from_state FS' % ueid,
   699                                        [{'WF': 'TrInfo', 'FS': 'State', 'U': 'CWUser'}])],
   702                                        [{'WF': 'TrInfo', 'FS': 'State', 'U': 'CWUser'}])],
   700                      None, None, [self.system], {}, [])],
   703                      None, None, [self.system], {}, [])],
   701                    {'x': ueid})
   704                    {'x': ueid})
   702 
   705 
   703 
   706 
   749                      None, None,
   752                      None, None,
   750                      [self.cards, self.system], {}, [])
   753                      [self.cards, self.system], {}, [])
   751                     ])
   754                     ])
   752 
   755 
   753     def test_not_identity(self):
   756     def test_not_identity(self):
   754         self._test('Any X WHERE NOT X identity U, U eid %s' % self.session.user.eid,
   757         ueid = self.session.user.eid
       
   758         self._test('Any X WHERE NOT X identity U, U eid %s' % ueid,
   755                    [('OneFetchStep',
   759                    [('OneFetchStep',
   756                      [('Any X WHERE NOT X identity 5, X is CWUser', [{'X': 'CWUser'}])],
   760                      [('Any X WHERE NOT X identity %s, X is CWUser' % ueid, [{'X': 'CWUser'}])],
   757                      None, None,
   761                      None, None,
   758                      [self.ldap, self.system], {}, [])
   762                      [self.ldap, self.system], {}, [])
   759                     ])
   763                     ])
   760 
   764 
   761     def test_outer_supported_rel2(self):
   765     def test_outer_supported_rel2(self):
   775                     ])
   779                     ])
   776 
   780 
   777     def test_security_has_text(self):
   781     def test_security_has_text(self):
   778         # use a guest user
   782         # use a guest user
   779         self.session = self.user_groups_session('guests')
   783         self.session = self.user_groups_session('guests')
       
   784         ueid = self.session.user.eid
   780         self._test('Any X WHERE X has_text "bla"',
   785         self._test('Any X WHERE X has_text "bla"',
   781                    [('FetchStep', [('Any E WHERE E type "X", E is Note', [{'E': 'Note'}])],
   786                    [('FetchStep', [('Any E WHERE E type "X", E is Note', [{'E': 'Note'}])],
   782                      [self.cards, self.system], None, {'E': 'table0.C0'}, []),
   787                      [self.cards, self.system], None, {'E': 'table0.C0'}, []),
   783                     ('UnionStep', None, None,
   788                     ('UnionStep', None, None,
   784                      [('OneFetchStep',
   789                      [('OneFetchStep',
   785                        [(u'Any X WHERE X has_text "bla", (EXISTS(X owned_by 5)) OR ((((EXISTS(D concerne C?, C owned_by 5, C type "X", X identity D, C is Division, D is Affaire)) OR (EXISTS(H concerne G?, G owned_by 5, G type "X", X identity H, G is SubDivision, H is Affaire))) OR (EXISTS(I concerne F?, F owned_by 5, F type "X", X identity I, F is Societe, I is Affaire))) OR (EXISTS(J concerne E?, E owned_by 5, X identity J, E is Note, J is Affaire))), X is Affaire',
   790                        [(u'Any X WHERE X has_text "bla", (EXISTS(X owned_by %(ueid)s)) OR ((((EXISTS(D concerne C?, C owned_by %(ueid)s, C type "X", X identity D, C is Division, D is Affaire)) OR (EXISTS(H concerne G?, G owned_by %(ueid)s, G type "X", X identity H, G is SubDivision, H is Affaire))) OR (EXISTS(I concerne F?, F owned_by %(ueid)s, F type "X", X identity I, F is Societe, I is Affaire))) OR (EXISTS(J concerne E?, E owned_by %(ueid)s, X identity J, E is Note, J is Affaire))), X is Affaire' % {'ueid': ueid},
   786                          [{'C': 'Division', 'E': 'Note', 'D': 'Affaire', 'G': 'SubDivision', 'F': 'Societe', 'I': 'Affaire', 'H': 'Affaire', 'J': 'Affaire', 'X': 'Affaire'}])],
   791                          [{'C': 'Division', 'E': 'Note', 'D': 'Affaire', 'G': 'SubDivision', 'F': 'Societe', 'I': 'Affaire', 'H': 'Affaire', 'J': 'Affaire', 'X': 'Affaire'}])],
   787                        None, None, [self.system], {'E': 'table0.C0'}, []),
   792                        None, None, [self.system], {'E': 'table0.C0'}, []),
   788                       ('OneFetchStep',
   793                       ('OneFetchStep',
   789                        [('Any X WHERE X has_text "bla", EXISTS(X owned_by 5), X is Basket',
   794                        [('Any X WHERE X has_text "bla", EXISTS(X owned_by %s), X is Basket' % ueid,
   790                          [{'X': 'Basket'}]),
   795                          [{'X': 'Basket'}]),
   791                         ('Any X WHERE X has_text "bla", EXISTS(X owned_by 5), X is CWUser',
   796                         ('Any X WHERE X has_text "bla", EXISTS(X owned_by %s), X is CWUser' % ueid,
   792                          [{'X': 'CWUser'}]),
   797                          [{'X': 'CWUser'}]),
   793                         ('Any X WHERE X has_text "bla", X is IN(Card, Comment, Division, Email, EmailThread, File, Folder, Note, Personne, Societe, SubDivision, Tag)',
   798                         ('Any X WHERE X has_text "bla", X is IN(Card, Comment, Division, Email, EmailThread, File, Folder, Note, Personne, Societe, SubDivision, Tag)',
   794                          [{'X': 'Card'}, {'X': 'Comment'},
   799                          [{'X': 'Card'}, {'X': 'Comment'},
   795                           {'X': 'Division'}, {'X': 'Email'}, {'X': 'EmailThread'},
   800                           {'X': 'Division'}, {'X': 'Email'}, {'X': 'EmailThread'},
   796                           {'X': 'File'}, {'X': 'Folder'},
   801                           {'X': 'File'}, {'X': 'Folder'},
   801                      ])
   806                      ])
   802 
   807 
   803     def test_security_has_text_limit_offset(self):
   808     def test_security_has_text_limit_offset(self):
   804         # use a guest user
   809         # use a guest user
   805         self.session = self.user_groups_session('guests')
   810         self.session = self.user_groups_session('guests')
       
   811         ueid = self.session.user.eid
   806         # note: same as the above query but because of the subquery usage, the display differs (not printing solutions for each union)
   812         # note: same as the above query but because of the subquery usage, the display differs (not printing solutions for each union)
   807         self._test('Any X LIMIT 10 OFFSET 10 WHERE X has_text "bla"',
   813         self._test('Any X LIMIT 10 OFFSET 10 WHERE X has_text "bla"',
   808                    [('FetchStep', [('Any E WHERE E type "X", E is Note', [{'E': 'Note'}])],
   814                    [('FetchStep', [('Any E WHERE E type "X", E is Note', [{'E': 'Note'}])],
   809                       [self.cards, self.system], None, {'E': 'table1.C0'}, []),
   815                       [self.cards, self.system], None, {'E': 'table1.C0'}, []),
   810                      ('UnionFetchStep', [
   816                      ('UnionFetchStep', [
   811                          ('FetchStep', [('Any X WHERE X has_text "bla", (EXISTS(X owned_by 5)) OR ((((EXISTS(D concerne C?, C owned_by 5, C type "X", X identity D, C is Division, D is Affaire)) OR (EXISTS(H concerne G?, G owned_by 5, G type "X", X identity H, G is SubDivision, H is Affaire))) OR (EXISTS(I concerne F?, F owned_by 5, F type "X", X identity I, F is Societe, I is Affaire))) OR (EXISTS(J concerne E?, E owned_by 5, X identity J, E is Note, J is Affaire))), X is Affaire',
   817                         ('FetchStep', [('Any X WHERE X has_text "bla", (EXISTS(X owned_by %(ueid)s)) OR ((((EXISTS(D concerne C?, C owned_by %(ueid)s, C type "X", X identity D, C is Division, D is Affaire)) OR (EXISTS(H concerne G?, G owned_by %(ueid)s, G type "X", X identity H, G is SubDivision, H is Affaire))) OR (EXISTS(I concerne F?, F owned_by %(ueid)s, F type "X", X identity I, F is Societe, I is Affaire))) OR (EXISTS(J concerne E?, E owned_by %(ueid)s, X identity J, E is Note, J is Affaire))), X is Affaire' % {'ueid': ueid},
   812                                             [{'C': 'Division', 'E': 'Note', 'D': 'Affaire', 'G': 'SubDivision', 'F': 'Societe', 'I': 'Affaire', 'H': 'Affaire', 'J': 'Affaire', 'X': 'Affaire'}])],
   818                                             [{'C': 'Division', 'E': 'Note', 'D': 'Affaire', 'G': 'SubDivision', 'F': 'Societe', 'I': 'Affaire', 'H': 'Affaire', 'J': 'Affaire', 'X': 'Affaire'}])],
   813                           [self.system], {'E': 'table1.C0'}, {'X': 'table0.C0'}, []),
   819                           [self.system], {'E': 'table1.C0'}, {'X': 'table0.C0'}, []),
   814                          ('FetchStep',
   820                          ('FetchStep',
   815                           [('Any X WHERE X has_text "bla", EXISTS(X owned_by 5), X is Basket',
   821                           [('Any X WHERE X has_text "bla", EXISTS(X owned_by %s), X is Basket' % ueid,
   816                             [{'X': 'Basket'}]),
   822                             [{'X': 'Basket'}]),
   817                            ('Any X WHERE X has_text "bla", EXISTS(X owned_by 5), X is CWUser',
   823                            ('Any X WHERE X has_text "bla", EXISTS(X owned_by %s), X is CWUser' % ueid,
   818                             [{'X': 'CWUser'}]),
   824                             [{'X': 'CWUser'}]),
   819                            ('Any X WHERE X has_text "bla", X is IN(Card, Comment, Division, Email, EmailThread, File, Folder, Note, Personne, Societe, SubDivision, Tag)',
   825                            ('Any X WHERE X has_text "bla", X is IN(Card, Comment, Division, Email, EmailThread, File, Folder, Note, Personne, Societe, SubDivision, Tag)',
   820                             [{'X': 'Card'}, {'X': 'Comment'},
   826                             [{'X': 'Card'}, {'X': 'Comment'},
   821                              {'X': 'Division'}, {'X': 'Email'}, {'X': 'EmailThread'},
   827                              {'X': 'Division'}, {'X': 'Email'}, {'X': 'EmailThread'},
   822                              {'X': 'File'}, {'X': 'Folder'},
   828                              {'X': 'File'}, {'X': 'Folder'},
   837 
   843 
   838     def test_security_user(self):
   844     def test_security_user(self):
   839         """a guest user trying to see another user: EXISTS(X owned_by U) is automatically inserted"""
   845         """a guest user trying to see another user: EXISTS(X owned_by U) is automatically inserted"""
   840         # use a guest user
   846         # use a guest user
   841         self.session = self.user_groups_session('guests')
   847         self.session = self.user_groups_session('guests')
       
   848         ueid = self.session.user.eid
   842         self._test('Any X WHERE X login "bla"',
   849         self._test('Any X WHERE X login "bla"',
   843                    [('FetchStep',
   850                    [('FetchStep',
   844                      [('Any X WHERE X login "bla", X is CWUser', [{'X': 'CWUser'}])],
   851                      [('Any X WHERE X login "bla", X is CWUser', [{'X': 'CWUser'}])],
   845                      [self.ldap, self.system], None, {'X': 'table0.C0'}, []),
   852                      [self.ldap, self.system], None, {'X': 'table0.C0'}, []),
   846                     ('OneFetchStep',
   853                     ('OneFetchStep',
   847                      [('Any X WHERE EXISTS(X owned_by 5), X is CWUser', [{'X': 'CWUser'}])],
   854                      [('Any X WHERE EXISTS(X owned_by %s), X is CWUser' % ueid, [{'X': 'CWUser'}])],
   848                      None, None, [self.system], {'X': 'table0.C0'}, [])])
   855                      None, None, [self.system], {'X': 'table0.C0'}, [])])
   849 
   856 
   850     def test_security_complex_has_text(self):
   857     def test_security_complex_has_text(self):
   851         # use a guest user
   858         # use a guest user
   852         self.session = self.user_groups_session('guests')
   859         self.session = self.user_groups_session('guests')
       
   860         ueid = self.session.user.eid
   853         self._test('Any X WHERE X has_text "bla", X firstname "bla"',
   861         self._test('Any X WHERE X has_text "bla", X firstname "bla"',
   854                    [('FetchStep', [('Any X WHERE X firstname "bla", X is CWUser', [{'X': 'CWUser'}])],
   862                    [('FetchStep', [('Any X WHERE X firstname "bla", X is CWUser', [{'X': 'CWUser'}])],
   855                      [self.ldap, self.system], None, {'X': 'table0.C0'}, []),
   863                      [self.ldap, self.system], None, {'X': 'table0.C0'}, []),
   856                     ('UnionStep', None, None, [
   864                     ('UnionStep', None, None, [
   857                         ('OneFetchStep', [('Any X WHERE X has_text "bla", EXISTS(X owned_by 5), X is CWUser', [{'X': 'CWUser'}])],
   865                         ('OneFetchStep', [('Any X WHERE X has_text "bla", EXISTS(X owned_by %s), X is CWUser' % ueid, [{'X': 'CWUser'}])],
   858                          None, None, [self.system], {'X': 'table0.C0'}, []),
   866                          None, None, [self.system], {'X': 'table0.C0'}, []),
   859                         ('OneFetchStep', [('Any X WHERE X has_text "bla", X firstname "bla", X is Personne', [{'X': 'Personne'}])],
   867                         ('OneFetchStep', [('Any X WHERE X has_text "bla", X firstname "bla", X is Personne', [{'X': 'Personne'}])],
   860                          None, None, [self.system], {}, []),
   868                          None, None, [self.system], {}, []),
   861                         ]),
   869                         ]),
   862                     ])
   870                     ])
   863 
   871 
   864     def test_security_complex_has_text_limit_offset(self):
   872     def test_security_complex_has_text_limit_offset(self):
   865         # use a guest user
   873         # use a guest user
   866         self.session = self.user_groups_session('guests')
   874         self.session = self.user_groups_session('guests')
       
   875         ueid = self.session.user.eid
   867         self._test('Any X LIMIT 10 OFFSET 10 WHERE X has_text "bla", X firstname "bla"',
   876         self._test('Any X LIMIT 10 OFFSET 10 WHERE X has_text "bla", X firstname "bla"',
   868                    [('FetchStep', [('Any X WHERE X firstname "bla", X is CWUser', [{'X': 'CWUser'}])],
   877                    [('FetchStep', [('Any X WHERE X firstname "bla", X is CWUser', [{'X': 'CWUser'}])],
   869                      [self.ldap, self.system], None, {'X': 'table1.C0'}, []),
   878                      [self.ldap, self.system], None, {'X': 'table1.C0'}, []),
   870                     ('UnionFetchStep', [
   879                     ('UnionFetchStep', [
   871                         ('FetchStep', [('Any X WHERE X has_text "bla", EXISTS(X owned_by 5), X is CWUser', [{'X': 'CWUser'}])],
   880                         ('FetchStep', [('Any X WHERE X has_text "bla", EXISTS(X owned_by %s), X is CWUser' % ueid, [{'X': 'CWUser'}])],
   872                          [self.system], {'X': 'table1.C0'}, {'X': 'table0.C0'}, []),
   881                          [self.system], {'X': 'table1.C0'}, {'X': 'table0.C0'}, []),
   873                         ('FetchStep', [('Any X WHERE X has_text "bla", X firstname "bla", X is Personne', [{'X': 'Personne'}])],
   882                         ('FetchStep', [('Any X WHERE X has_text "bla", X firstname "bla", X is Personne', [{'X': 'Personne'}])],
   874                          [self.system], {}, {'X': 'table0.C0'}, []),
   883                          [self.system], {}, {'X': 'table0.C0'}, []),
   875                         ]),
   884                         ]),
   876                      ('OneFetchStep',
   885                      ('OneFetchStep',
   879                     ])
   888                     ])
   880 
   889 
   881     def test_security_complex_aggregat(self):
   890     def test_security_complex_aggregat(self):
   882         # use a guest user
   891         # use a guest user
   883         self.session = self.user_groups_session('guests')
   892         self.session = self.user_groups_session('guests')
       
   893         ueid = self.session.user.eid
       
   894         ALL_SOLS = X_ALL_SOLS[:]
       
   895         ALL_SOLS.remove({'X': 'CWSourceHostConfig'}) # not authorized
   884         self._test('Any MAX(X)',
   896         self._test('Any MAX(X)',
   885                    [('FetchStep', [('Any E WHERE E type "X", E is Note', [{'E': 'Note'}])],
   897                    [('FetchStep', [('Any E WHERE E type "X", E is Note', [{'E': 'Note'}])],
   886                      [self.cards, self.system],  None, {'E': 'table1.C0'}, []),
   898                      [self.cards, self.system],  None, {'E': 'table1.C0'}, []),
   887                     ('FetchStep', [('Any X WHERE X is CWUser', [{'X': 'CWUser'}])],
   899                     ('FetchStep', [('Any X WHERE X is CWUser', [{'X': 'CWUser'}])],
   888                      [self.ldap, self.system], None, {'X': 'table2.C0'}, []),
   900                      [self.ldap, self.system], None, {'X': 'table2.C0'}, []),
   889                     ('UnionFetchStep', [
   901                     ('UnionFetchStep', [
   890                         ('FetchStep', [('Any X WHERE EXISTS(X owned_by 5), X is Basket', [{'X': 'Basket'}])],
   902                         ('FetchStep', [('Any X WHERE EXISTS(X owned_by %s), X is Basket' % ueid, [{'X': 'Basket'}])],
   891                           [self.system], {}, {'X': 'table0.C0'}, []),
   903                           [self.system], {}, {'X': 'table0.C0'}, []),
   892                         ('UnionFetchStep',
   904                         ('UnionFetchStep',
   893                          [('FetchStep', [('Any X WHERE X is IN(Card, Note, State)',
   905                          [('FetchStep', [('Any X WHERE X is IN(Card, Note, State)',
   894                                           [{'X': 'Card'}, {'X': 'Note'}, {'X': 'State'}])],
   906                                           [{'X': 'Card'}, {'X': 'Note'}, {'X': 'State'}])],
   895                            [self.cards, self.system], {}, {'X': 'table0.C0'}, []),
   907                            [self.cards, self.system], {}, {'X': 'table0.C0'}, []),
   896                           ('FetchStep',
   908                           ('FetchStep',
   897                            [('Any X WHERE X is IN(BaseTransition, Bookmark, CWAttribute, CWCache, CWConstraint, CWConstraintType, CWEType, CWGroup, CWPermission, CWProperty, CWRType, CWRelation, CWUniqueTogetherConstraint, Comment, Division, Email, EmailAddress, EmailPart, EmailThread, ExternalUri, File, Folder, Personne, RQLExpression, Societe, SubDivision, SubWorkflowExitPoint, Tag, TrInfo, Transition, Workflow, WorkflowTransition)',
   909                            [('Any X WHERE X is IN(BaseTransition, Bookmark, CWAttribute, CWCache, CWConstraint, CWConstraintType, CWEType, CWGroup, CWPermission, CWProperty, CWRType, CWRelation, CWSource, CWUniqueTogetherConstraint, Comment, Division, Email, EmailAddress, EmailPart, EmailThread, ExternalUri, File, Folder, Personne, RQLExpression, Societe, SubDivision, SubWorkflowExitPoint, Tag, TrInfo, Transition, Workflow, WorkflowTransition)',
   898                              [{'X': 'BaseTransition'}, {'X': 'Bookmark'},
   910                              [{'X': 'BaseTransition'}, {'X': 'Bookmark'},
   899                               {'X': 'CWAttribute'}, {'X': 'CWCache'},
   911                               {'X': 'CWAttribute'}, {'X': 'CWCache'},
   900                               {'X': 'CWConstraint'}, {'X': 'CWConstraintType'},
   912                               {'X': 'CWConstraint'}, {'X': 'CWConstraintType'},
   901                               {'X': 'CWEType'}, {'X': 'CWGroup'},
   913                               {'X': 'CWEType'}, {'X': 'CWGroup'},
   902                               {'X': 'CWPermission'}, {'X': 'CWProperty'},
   914                               {'X': 'CWPermission'}, {'X': 'CWProperty'},
   903                               {'X': 'CWRType'}, {'X': 'CWRelation'},
   915                               {'X': 'CWRType'}, {'X': 'CWRelation'},
       
   916                               {'X': 'CWSource'},
   904                               {'X': 'CWUniqueTogetherConstraint'},
   917                               {'X': 'CWUniqueTogetherConstraint'},
   905                               {'X': 'Comment'}, {'X': 'Division'},
   918                               {'X': 'Comment'}, {'X': 'Division'},
   906                               {'X': 'Email'}, {'X': 'EmailAddress'},
   919                               {'X': 'Email'}, {'X': 'EmailAddress'},
   907                               {'X': 'EmailPart'}, {'X': 'EmailThread'},
   920                               {'X': 'EmailPart'}, {'X': 'EmailThread'},
   908                               {'X': 'ExternalUri'}, {'X': 'File'},
   921                               {'X': 'ExternalUri'}, {'X': 'File'},
   912                               {'X': 'SubWorkflowExitPoint'}, {'X': 'Tag'},
   925                               {'X': 'SubWorkflowExitPoint'}, {'X': 'Tag'},
   913                               {'X': 'TrInfo'}, {'X': 'Transition'},
   926                               {'X': 'TrInfo'}, {'X': 'Transition'},
   914                               {'X': 'Workflow'}, {'X': 'WorkflowTransition'}])],
   927                               {'X': 'Workflow'}, {'X': 'WorkflowTransition'}])],
   915                            [self.system], {}, {'X': 'table0.C0'}, []),
   928                            [self.system], {}, {'X': 'table0.C0'}, []),
   916                           ]),
   929                           ]),
   917                         ('FetchStep', [('Any X WHERE EXISTS(X owned_by 5), X is CWUser', [{'X': 'CWUser'}])],
   930                         ('FetchStep', [('Any X WHERE EXISTS(X owned_by %s), X is CWUser' % ueid, [{'X': 'CWUser'}])],
   918                          [self.system], {'X': 'table2.C0'}, {'X': 'table0.C0'}, []),
   931                          [self.system], {'X': 'table2.C0'}, {'X': 'table0.C0'}, []),
   919                         ('FetchStep', [('Any X WHERE (EXISTS(X owned_by 5)) OR ((((EXISTS(D concerne C?, C owned_by 5, C type "X", X identity D, C is Division, D is Affaire)) OR (EXISTS(H concerne G?, G owned_by 5, G type "X", X identity H, G is SubDivision, H is Affaire))) OR (EXISTS(I concerne F?, F owned_by 5, F type "X", X identity I, F is Societe, I is Affaire))) OR (EXISTS(J concerne E?, E owned_by 5, X identity J, E is Note, J is Affaire))), X is Affaire',
   932                         ('FetchStep', [('Any X WHERE (EXISTS(X owned_by %(ueid)s)) OR ((((EXISTS(D concerne C?, C owned_by %(ueid)s, C type "X", X identity D, C is Division, D is Affaire)) OR (EXISTS(H concerne G?, G owned_by %(ueid)s, G type "X", X identity H, G is SubDivision, H is Affaire))) OR (EXISTS(I concerne F?, F owned_by %(ueid)s, F type "X", X identity I, F is Societe, I is Affaire))) OR (EXISTS(J concerne E?, E owned_by %(ueid)s, X identity J, E is Note, J is Affaire))), X is Affaire' % {'ueid': ueid},
   920                                         [{'C': 'Division', 'E': 'Note', 'D': 'Affaire', 'G': 'SubDivision', 'F': 'Societe', 'I': 'Affaire', 'H': 'Affaire', 'J': 'Affaire', 'X': 'Affaire'}])],
   933                                         [{'C': 'Division', 'E': 'Note', 'D': 'Affaire', 'G': 'SubDivision', 'F': 'Societe', 'I': 'Affaire', 'H': 'Affaire', 'J': 'Affaire', 'X': 'Affaire'}])],
   921                          [self.system], {'E': 'table1.C0'}, {'X': 'table0.C0'}, []),
   934                          [self.system], {'E': 'table1.C0'}, {'X': 'table0.C0'}, []),
   922                         ]),
   935                         ]),
   923                     ('OneFetchStep', [('Any MAX(X)', X_ALL_SOLS)],
   936                     ('OneFetchStep', [('Any MAX(X)', ALL_SOLS)],
   924                      None, None, [self.system], {'X': 'table0.C0'}, [])
   937                      None, None, [self.system], {'X': 'table0.C0'}, [])
   925                     ])
   938                     ])
   926 
   939 
   927     def test_security_complex_aggregat2(self):
   940     def test_security_complex_aggregat2(self):
   928         # use a guest user
   941         # use a guest user
   929         self.session = self.user_groups_session('guests')
   942         self.session = self.user_groups_session('guests')
       
   943         ueid = self.session.user.eid
   930         X_ET_ALL_SOLS = []
   944         X_ET_ALL_SOLS = []
   931         for s in X_ALL_SOLS:
   945         for s in X_ALL_SOLS:
       
   946             if s == {'X': 'CWSourceHostConfig'}:
       
   947                 continue # not authorized
   932             ets = {'ET': 'CWEType'}
   948             ets = {'ET': 'CWEType'}
   933             ets.update(s)
   949             ets.update(s)
   934             X_ET_ALL_SOLS.append(ets)
   950             X_ET_ALL_SOLS.append(ets)
   935         self._test('Any ET, COUNT(X) GROUPBY ET ORDERBY ET WHERE X is ET',
   951         self._test('Any ET, COUNT(X) GROUPBY ET ORDERBY ET WHERE X is ET',
   936                    [('FetchStep', [('Any X WHERE X is IN(Card, Note, State)',
   952                    [('FetchStep', [('Any X WHERE X is IN(Card, Note, State)',
   939                     ('FetchStep', [('Any E WHERE E type "X", E is Note', [{'E': 'Note'}])],
   955                     ('FetchStep', [('Any E WHERE E type "X", E is Note', [{'E': 'Note'}])],
   940                      [self.cards, self.system],  None, {'E': 'table2.C0'}, []),
   956                      [self.cards, self.system],  None, {'E': 'table2.C0'}, []),
   941                     ('FetchStep', [('Any X WHERE X is CWUser', [{'X': 'CWUser'}])],
   957                     ('FetchStep', [('Any X WHERE X is CWUser', [{'X': 'CWUser'}])],
   942                      [self.ldap, self.system], None, {'X': 'table3.C0'}, []),
   958                      [self.ldap, self.system], None, {'X': 'table3.C0'}, []),
   943                     ('UnionFetchStep',
   959                     ('UnionFetchStep',
   944                      [('FetchStep', [('Any ET,X WHERE X is ET, EXISTS(X owned_by 5), ET is CWEType, X is Basket',
   960                      [('FetchStep', [('Any ET,X WHERE X is ET, EXISTS(X owned_by %s), ET is CWEType, X is Basket' % ueid,
   945                                       [{'ET': 'CWEType', 'X': 'Basket'}])],
   961                                       [{'ET': 'CWEType', 'X': 'Basket'}])],
   946                        [self.system], {}, {'ET': 'table0.C0', 'X': 'table0.C1'}, []),
   962                        [self.system], {}, {'ET': 'table0.C0', 'X': 'table0.C1'}, []),
   947                       ('FetchStep', [('Any ET,X WHERE X is ET, (EXISTS(X owned_by 5)) OR ((((EXISTS(D concerne C?, C owned_by 5, C type "X", X identity D, C is Division, D is Affaire)) OR (EXISTS(H concerne G?, G owned_by 5, G type "X", X identity H, G is SubDivision, H is Affaire))) OR (EXISTS(I concerne F?, F owned_by 5, F type "X", X identity I, F is Societe, I is Affaire))) OR (EXISTS(J concerne E?, E owned_by 5, X identity J, E is Note, J is Affaire))), ET is CWEType, X is Affaire',
   963                       ('FetchStep', [('Any ET,X WHERE X is ET, (EXISTS(X owned_by %(ueid)s)) OR ((((EXISTS(D concerne C?, C owned_by %(ueid)s, C type "X", X identity D, C is Division, D is Affaire)) OR (EXISTS(H concerne G?, G owned_by %(ueid)s, G type "X", X identity H, G is SubDivision, H is Affaire))) OR (EXISTS(I concerne F?, F owned_by %(ueid)s, F type "X", X identity I, F is Societe, I is Affaire))) OR (EXISTS(J concerne E?, E owned_by %(ueid)s, X identity J, E is Note, J is Affaire))), ET is CWEType, X is Affaire' % {'ueid': ueid},
   948                                       [{'C': 'Division', 'E': 'Note', 'D': 'Affaire',
   964                                       [{'C': 'Division', 'E': 'Note', 'D': 'Affaire',
   949                                         'G': 'SubDivision', 'F': 'Societe', 'I': 'Affaire',
   965                                         'G': 'SubDivision', 'F': 'Societe', 'I': 'Affaire',
   950                                         'H': 'Affaire', 'J': 'Affaire', 'X': 'Affaire',
   966                                         'H': 'Affaire', 'J': 'Affaire', 'X': 'Affaire',
   951                                         'ET': 'CWEType'}])],
   967                                         'ET': 'CWEType'}])],
   952                        [self.system], {'E': 'table2.C0'}, {'ET': 'table0.C0', 'X': 'table0.C1'},
   968                        [self.system], {'E': 'table2.C0'}, {'ET': 'table0.C0', 'X': 'table0.C1'},
   953                        []),
   969                        []),
   954                       ('FetchStep', [('Any ET,X WHERE X is ET, EXISTS(X owned_by 5), ET is CWEType, X is CWUser',
   970                       ('FetchStep', [('Any ET,X WHERE X is ET, EXISTS(X owned_by %s), ET is CWEType, X is CWUser' % ueid,
   955                                       [{'ET': 'CWEType', 'X': 'CWUser'}])],
   971                                       [{'ET': 'CWEType', 'X': 'CWUser'}])],
   956                        [self.system], {'X': 'table3.C0'}, {'ET': 'table0.C0', 'X': 'table0.C1'}, []),
   972                        [self.system], {'X': 'table3.C0'}, {'ET': 'table0.C0', 'X': 'table0.C1'}, []),
   957                       # extra UnionFetchStep could be avoided but has no cost, so don't care
   973                       # extra UnionFetchStep could be avoided but has no cost, so don't care
   958                       ('UnionFetchStep',
   974                       ('UnionFetchStep',
   959                        [('FetchStep', [('Any ET,X WHERE X is ET, ET is CWEType, X is IN(BaseTransition, Bookmark, CWAttribute, CWCache, CWConstraint, CWConstraintType, CWEType, CWGroup, CWPermission, CWProperty, CWRType, CWRelation, CWUniqueTogetherConstraint, Comment, Division, Email, EmailAddress, EmailPart, EmailThread, ExternalUri, File, Folder, Personne, RQLExpression, Societe, SubDivision, SubWorkflowExitPoint, Tag, TrInfo, Transition, Workflow, WorkflowTransition)',
   975                        [('FetchStep', [('Any ET,X WHERE X is ET, ET is CWEType, X is IN(BaseTransition, Bookmark, CWAttribute, CWCache, CWConstraint, CWConstraintType, CWEType, CWGroup, CWPermission, CWProperty, CWRType, CWRelation, CWSource, CWUniqueTogetherConstraint, Comment, Division, Email, EmailAddress, EmailPart, EmailThread, ExternalUri, File, Folder, Personne, RQLExpression, Societe, SubDivision, SubWorkflowExitPoint, Tag, TrInfo, Transition, Workflow, WorkflowTransition)',
   960                                         [{'X': 'BaseTransition', 'ET': 'CWEType'},
   976                                         [{'X': 'BaseTransition', 'ET': 'CWEType'},
   961                                          {'X': 'Bookmark', 'ET': 'CWEType'}, {'X': 'CWAttribute', 'ET': 'CWEType'},
   977                                          {'X': 'Bookmark', 'ET': 'CWEType'}, {'X': 'CWAttribute', 'ET': 'CWEType'},
   962                                          {'X': 'CWCache', 'ET': 'CWEType'}, {'X': 'CWConstraint', 'ET': 'CWEType'},
   978                                          {'X': 'CWCache', 'ET': 'CWEType'}, {'X': 'CWConstraint', 'ET': 'CWEType'},
   963                                          {'X': 'CWConstraintType', 'ET': 'CWEType'}, {'X': 'CWEType', 'ET': 'CWEType'},
   979                                          {'X': 'CWConstraintType', 'ET': 'CWEType'}, {'X': 'CWEType', 'ET': 'CWEType'},
   964                                          {'X': 'CWGroup', 'ET': 'CWEType'}, {'X': 'CWPermission', 'ET': 'CWEType'},
   980                                          {'X': 'CWGroup', 'ET': 'CWEType'}, {'X': 'CWPermission', 'ET': 'CWEType'},
   965                                          {'X': 'CWProperty', 'ET': 'CWEType'}, {'X': 'CWRType', 'ET': 'CWEType'},
   981                                          {'X': 'CWProperty', 'ET': 'CWEType'}, {'X': 'CWRType', 'ET': 'CWEType'},
       
   982                                          {'X': 'CWSource', 'ET': 'CWEType'},
   966                                          {'X': 'CWRelation', 'ET': 'CWEType'},
   983                                          {'X': 'CWRelation', 'ET': 'CWEType'},
   967                                          {'X': 'CWUniqueTogetherConstraint', 'ET': 'CWEType'},
   984                                          {'X': 'CWUniqueTogetherConstraint', 'ET': 'CWEType'},
   968                                          {'X': 'Comment', 'ET': 'CWEType'},
   985                                          {'X': 'Comment', 'ET': 'CWEType'},
   969                                          {'X': 'Division', 'ET': 'CWEType'}, {'X': 'Email', 'ET': 'CWEType'},
   986                                          {'X': 'Division', 'ET': 'CWEType'}, {'X': 'Email', 'ET': 'CWEType'},
   970                                          {'X': 'EmailAddress', 'ET': 'CWEType'}, {'X': 'EmailPart', 'ET': 'CWEType'},
   987                                          {'X': 'EmailAddress', 'ET': 'CWEType'}, {'X': 'EmailPart', 'ET': 'CWEType'},
   991                     ])
  1008                     ])
   992 
  1009 
   993     def test_security_3sources(self):
  1010     def test_security_3sources(self):
   994         # use a guest user
  1011         # use a guest user
   995         self.session = self.user_groups_session('guests')
  1012         self.session = self.user_groups_session('guests')
       
  1013         ueid = self.session.user.eid
   996         self._test('Any X, XT WHERE X is Card, X owned_by U, X title XT, U login "syt"',
  1014         self._test('Any X, XT WHERE X is Card, X owned_by U, X title XT, U login "syt"',
   997                    [('FetchStep',
  1015                    [('FetchStep',
   998                      [('Any X,XT WHERE X title XT, X is Card', [{'X': 'Card', 'XT': 'String'}])],
  1016                      [('Any X,XT WHERE X title XT, X is Card', [{'X': 'Card', 'XT': 'String'}])],
   999                      [self.cards, self.system], None, {'X': 'table0.C0', 'X.title': 'table0.C1', 'XT': 'table0.C1'}, []),
  1017                      [self.cards, self.system], None, {'X': 'table0.C0', 'X.title': 'table0.C1', 'XT': 'table0.C1'}, []),
  1000                     ('FetchStep',
  1018                     ('FetchStep',
  1001                      [('Any U WHERE U login "syt", U is CWUser', [{'U': 'CWUser'}])],
  1019                      [('Any U WHERE U login "syt", U is CWUser', [{'U': 'CWUser'}])],
  1002                      [self.ldap, self.system], None, {'U': 'table1.C0'}, []),
  1020                      [self.ldap, self.system], None, {'U': 'table1.C0'}, []),
  1003                     ('OneFetchStep',
  1021                     ('OneFetchStep',
  1004                      [('Any X,XT WHERE X owned_by U, X title XT, EXISTS(U owned_by 5), U is CWUser, X is Card',
  1022                      [('Any X,XT WHERE X owned_by U, X title XT, EXISTS(U owned_by %s), U is CWUser, X is Card' % ueid,
  1005                        [{'X': 'Card', 'U': 'CWUser', 'XT': 'String'}])],
  1023                        [{'X': 'Card', 'U': 'CWUser', 'XT': 'String'}])],
  1006                      None, None, [self.system],
  1024                      None, None, [self.system],
  1007                      {'X': 'table0.C0', 'X.title': 'table0.C1', 'XT': 'table0.C1', 'U': 'table1.C0'}, [])
  1025                      {'X': 'table0.C0', 'X.title': 'table0.C1', 'XT': 'table0.C1', 'U': 'table1.C0'}, [])
  1008                     ])
  1026                     ])
  1009 
  1027 
  1010     def test_security_3sources_identity(self):
  1028     def test_security_3sources_identity(self):
  1011         self.restore_orig_cwuser_security()
  1029         self.restore_orig_cwuser_security()
  1012         # use a guest user
  1030         # use a guest user
  1013         self.session = self.user_groups_session('guests')
  1031         self.session = self.user_groups_session('guests')
       
  1032         ueid = self.session.user.eid
  1014         self._test('Any X, XT WHERE X is Card, X owned_by U, X title XT, U login "syt"',
  1033         self._test('Any X, XT WHERE X is Card, X owned_by U, X title XT, U login "syt"',
  1015                    [('FetchStep',
  1034                    [('FetchStep',
  1016                      [('Any X,XT WHERE X title XT, X is Card', [{'X': 'Card', 'XT': 'String'}])],
  1035                      [('Any X,XT WHERE X title XT, X is Card', [{'X': 'Card', 'XT': 'String'}])],
  1017                      [self.cards, self.system], None, {'X': 'table0.C0', 'X.title': 'table0.C1', 'XT': 'table0.C1'}, []),
  1036                      [self.cards, self.system], None, {'X': 'table0.C0', 'X.title': 'table0.C1', 'XT': 'table0.C1'}, []),
  1018                     ('OneFetchStep',
  1037                     ('OneFetchStep',
  1019                      [('Any X,XT WHERE X owned_by U, X title XT, U login "syt", EXISTS(U identity 5), U is CWUser, X is Card',
  1038                      [('Any X,XT WHERE X owned_by U, X title XT, U login "syt", EXISTS(U identity %s), U is CWUser, X is Card' % ueid,
  1020                        [{'U': 'CWUser', 'X': 'Card', 'XT': 'String'}])],
  1039                        [{'U': 'CWUser', 'X': 'Card', 'XT': 'String'}])],
  1021                      None, None, [self.system], {'X': 'table0.C0', 'X.title': 'table0.C1', 'XT': 'table0.C1'}, [])
  1040                      None, None, [self.system], {'X': 'table0.C0', 'X.title': 'table0.C1', 'XT': 'table0.C1'}, [])
  1022                     ])
  1041                     ])
  1023 
  1042 
  1024     def test_security_3sources_identity_optional_var(self):
  1043     def test_security_3sources_identity_optional_var(self):
  1025         self.restore_orig_cwuser_security()
  1044         self.restore_orig_cwuser_security()
  1026         # use a guest user
  1045         # use a guest user
  1027         self.session = self.user_groups_session('guests')
  1046         self.session = self.user_groups_session('guests')
       
  1047         ueid = self.session.user.eid
  1028         self._test('Any X,XT,U WHERE X is Card, X owned_by U?, X title XT, U login L',
  1048         self._test('Any X,XT,U WHERE X is Card, X owned_by U?, X title XT, U login L',
  1029                    [('FetchStep',
  1049                    [('FetchStep',
  1030                      [('Any U,L WHERE U login L, EXISTS(U identity 5), U is CWUser',
  1050                      [('Any U,L WHERE U login L, EXISTS(U identity %s), U is CWUser' % ueid,
  1031                        [{'L': 'String', u'U': 'CWUser'}])],
  1051                        [{'L': 'String', u'U': 'CWUser'}])],
  1032                      [self.system], {}, {'L': 'table0.C1', 'U': 'table0.C0', 'U.login': 'table0.C1'}, []),
  1052                      [self.system], {}, {'L': 'table0.C1', 'U': 'table0.C0', 'U.login': 'table0.C1'}, []),
  1033                     ('FetchStep',
  1053                     ('FetchStep',
  1034                      [('Any X,XT WHERE X title XT, X is Card', [{'X': 'Card', 'XT': 'String'}])],
  1054                      [('Any X,XT WHERE X title XT, X is Card', [{'X': 'Card', 'XT': 'String'}])],
  1035                      [self.cards, self.system], None, {'X': 'table1.C0', 'X.title': 'table1.C1', 'XT': 'table1.C1'}, []),
  1055                      [self.cards, self.system], None, {'X': 'table1.C0', 'X.title': 'table1.C1', 'XT': 'table1.C1'}, []),
  1044                     ])
  1064                     ])
  1045 
  1065 
  1046     def test_security_3sources_limit_offset(self):
  1066     def test_security_3sources_limit_offset(self):
  1047         # use a guest user
  1067         # use a guest user
  1048         self.session = self.user_groups_session('guests')
  1068         self.session = self.user_groups_session('guests')
       
  1069         ueid = self.session.user.eid
  1049         self._test('Any X, XT LIMIT 10 OFFSET 10 WHERE X is Card, X owned_by U, X title XT, U login "syt"',
  1070         self._test('Any X, XT LIMIT 10 OFFSET 10 WHERE X is Card, X owned_by U, X title XT, U login "syt"',
  1050                    [('FetchStep',
  1071                    [('FetchStep',
  1051                      [('Any X,XT WHERE X title XT, X is Card', [{'X': 'Card', 'XT': 'String'}])],
  1072                      [('Any X,XT WHERE X title XT, X is Card', [{'X': 'Card', 'XT': 'String'}])],
  1052                      [self.cards, self.system], None, {'X': 'table0.C0', 'X.title': 'table0.C1', 'XT': 'table0.C1'}, []),
  1073                      [self.cards, self.system], None, {'X': 'table0.C0', 'X.title': 'table0.C1', 'XT': 'table0.C1'}, []),
  1053                     ('FetchStep',
  1074                     ('FetchStep',
  1054                      [('Any U WHERE U login "syt", U is CWUser', [{'U': 'CWUser'}])],
  1075                      [('Any U WHERE U login "syt", U is CWUser', [{'U': 'CWUser'}])],
  1055                      [self.ldap, self.system], None, {'U': 'table1.C0'}, []),
  1076                      [self.ldap, self.system], None, {'U': 'table1.C0'}, []),
  1056                     ('OneFetchStep',
  1077                     ('OneFetchStep',
  1057                      [('Any X,XT LIMIT 10 OFFSET 10 WHERE X owned_by U, X title XT, EXISTS(U owned_by 5), U is CWUser, X is Card',
  1078                      [('Any X,XT LIMIT 10 OFFSET 10 WHERE X owned_by U, X title XT, EXISTS(U owned_by %s), U is CWUser, X is Card' % ueid,
  1058                        [{'X': 'Card', 'U': 'CWUser', 'XT': 'String'}])],
  1079                        [{'X': 'Card', 'U': 'CWUser', 'XT': 'String'}])],
  1059                      10, 10, [self.system],
  1080                      10, 10, [self.system],
  1060                      {'X': 'table0.C0', 'X.title': 'table0.C1', 'XT': 'table0.C1', 'U': 'table1.C0'}, [])
  1081                      {'X': 'table0.C0', 'X.title': 'table0.C1', 'XT': 'table0.C1', 'U': 'table1.C0'}, [])
  1061                     ])
  1082                     ])
  1062 
  1083 
  1148                                                   'X': 'table0.C0',
  1169                                                   'X': 'table0.C0',
  1149                                                   'X.firstname': 'table0.C2',
  1170                                                   'X.firstname': 'table0.C2',
  1150                                                   'X.login': 'table0.C1',
  1171                                                   'X.login': 'table0.C1',
  1151                                                   'X.modification_date': 'table0.C4',
  1172                                                   'X.modification_date': 'table0.C4',
  1152                                                   'X.surname': 'table0.C3'}, []),
  1173                                                   'X.surname': 'table0.C3'}, []),
  1153                 ('OneFetchStep', [('Any X,AA,AB,AC,AD ORDERBY AA WHERE X login AA, X firstname AB, X surname AC, X modification_date AD, EXISTS(((X identity 5) OR (EXISTS(X in_group C, C name IN("managers", "staff"), C is CWGroup))) OR (EXISTS(X in_group D, 5 in_group D, NOT D name "users", D is CWGroup))), X is CWUser',
  1174                 ('OneFetchStep', [('Any X,AA,AB,AC,AD ORDERBY AA WHERE X login AA, X firstname AB, X surname AC, X modification_date AD, EXISTS(((X identity %(ueid)s) OR (EXISTS(X in_group C, C name IN("managers", "staff"), C is CWGroup))) OR (EXISTS(X in_group D, %(ueid)s in_group D, NOT D name "users", D is CWGroup))), X is CWUser' % {'ueid': ueid},
  1154                                    [{'AA': 'String', 'AB': 'String', 'AC': 'String', 'AD': 'Datetime',
  1175                                    [{'AA': 'String', 'AB': 'String', 'AC': 'String', 'AD': 'Datetime',
  1155                                      'C': 'CWGroup', 'D': 'CWGroup', 'X': 'CWUser'}])],
  1176                                      'C': 'CWGroup', 'D': 'CWGroup', 'X': 'CWUser'}])],
  1156                  None, None, [self.system],
  1177                  None, None, [self.system],
  1157                  {'AA': 'table0.C1', 'AB': 'table0.C2', 'AC': 'table0.C3', 'AD': 'table0.C4',
  1178                  {'AA': 'table0.C1', 'AB': 'table0.C2', 'AC': 'table0.C3', 'AD': 'table0.C4',
  1158                   'X': 'table0.C0',
  1179                   'X': 'table0.C0',
  1225         # all states (eg from both sources) which are not related to entity with the
  1246         # all states (eg from both sources) which are not related to entity with the
  1226         # given eid. The "NOT X in_state S, X eid %(x)s" expression is necessarily true
  1247         # given eid. The "NOT X in_state S, X eid %(x)s" expression is necessarily true
  1227         # in the source where %(x)s is not coming from and will be removed during rql
  1248         # in the source where %(x)s is not coming from and will be removed during rql
  1228         # generation for the external source
  1249         # generation for the external source
  1229         self._test('Any SN WHERE NOT X in_state S, X eid %(x)s, S name SN',
  1250         self._test('Any SN WHERE NOT X in_state S, X eid %(x)s, S name SN',
  1230                    [('OneFetchStep', [('Any SN WHERE NOT EXISTS(5 in_state S), S name SN, S is State',
  1251                    [('OneFetchStep', [('Any SN WHERE NOT EXISTS(%s in_state S), S name SN, S is State' % ueid,
  1231                                        [{'S': 'State', 'SN': 'String'}])],
  1252                                        [{'S': 'State', 'SN': 'String'}])],
  1232                      None, None, [self.cards, self.system], {}, [])],
  1253                      None, None, [self.cards, self.system], {}, [])],
  1233                    {'x': ueid})
  1254                    {'x': ueid})
  1234 
  1255 
  1235     def test_not_relation_no_split_external(self):
  1256     def test_not_relation_no_split_external(self):
  1278                      {'A': 'table0.C0', 'A.creation_date': 'table0.C1', 'A.modification_date': 'table0.C2', 'C': 'table0.C2', 'B': 'table0.C1'}, [])],
  1299                      {'A': 'table0.C0', 'A.creation_date': 'table0.C1', 'A.modification_date': 'table0.C2', 'C': 'table0.C2', 'B': 'table0.C1'}, [])],
  1279                    {'x': 999999})
  1300                    {'x': 999999})
  1280 
  1301 
  1281 
  1302 
  1282     def test_simplified_var(self):
  1303     def test_simplified_var(self):
       
  1304         ueid = self.session.user.eid
  1283         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1305         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1284         self._test('Any U WHERE U in_group G, (G name IN ("managers", "logilab") OR (X require_permission P?, P name "bla", P require_group G)), X eid %(x)s, U eid %(u)s',
  1306         self._test('Any U WHERE U in_group G, (G name IN ("managers", "logilab") OR (X require_permission P?, P name "bla", P require_group G)), X eid %(x)s, U eid %(u)s',
  1285                    [('OneFetchStep', [('Any 5 WHERE 5 in_group G, (G name IN("managers", "logilab")) OR (X require_permission P?, P name "bla", P require_group G), X eid 999999',
  1307                    [('OneFetchStep', [('Any %s WHERE %s in_group G, (G name IN("managers", "logilab")) OR (X require_permission P?, P name "bla", P require_group G), X eid 999999' % (ueid, ueid),
  1286                                        [{'X': 'Note', 'G': 'CWGroup', 'P': 'CWPermission'}])],
  1308                                        [{'X': 'Note', 'G': 'CWGroup', 'P': 'CWPermission'}])],
  1287                      None, None, [self.system], {}, [])],
  1309                      None, None, [self.system], {}, [])],
  1288                    {'x': 999999, 'u': self.session.user.eid})
  1310                    {'x': 999999, 'u': ueid})
  1289 
  1311 
  1290     def test_has_text(self):
  1312     def test_has_text(self):
  1291         self._test('Card X WHERE X has_text "toto"',
  1313         self._test('Card X WHERE X has_text "toto"',
  1292                    [('OneFetchStep', [('Any X WHERE X has_text "toto", X is Card',
  1314                    [('OneFetchStep', [('Any X WHERE X has_text "toto", X is Card',
  1293                                        [{'X': 'Card'}])],
  1315                                        [{'X': 'Card'}])],
  1323                     ])
  1345                     ])
  1324 
  1346 
  1325     def test_security_has_text_orderby_rank(self):
  1347     def test_security_has_text_orderby_rank(self):
  1326         # use a guest user
  1348         # use a guest user
  1327         self.session = self.user_groups_session('guests')
  1349         self.session = self.user_groups_session('guests')
       
  1350         ueid = self.session.user.eid
  1328         self._test('Any X ORDERBY FTIRANK(X) WHERE X has_text "bla", X firstname "bla"',
  1351         self._test('Any X ORDERBY FTIRANK(X) WHERE X has_text "bla", X firstname "bla"',
  1329                    [('FetchStep', [('Any X WHERE X firstname "bla", X is CWUser', [{'X': 'CWUser'}])],
  1352                    [('FetchStep', [('Any X WHERE X firstname "bla", X is CWUser', [{'X': 'CWUser'}])],
  1330                      [self.ldap, self.system], None, {'X': 'table1.C0'}, []),
  1353                      [self.ldap, self.system], None, {'X': 'table1.C0'}, []),
  1331                     ('UnionFetchStep',
  1354                     ('UnionFetchStep',
  1332                      [('FetchStep', [('Any X WHERE X firstname "bla", X is Personne', [{'X': 'Personne'}])],
  1355                      [('FetchStep', [('Any X WHERE X firstname "bla", X is Personne', [{'X': 'Personne'}])],
  1333                        [self.system], {}, {'X': 'table0.C0'}, []),
  1356                        [self.system], {}, {'X': 'table0.C0'}, []),
  1334                       ('FetchStep', [('Any X WHERE EXISTS(X owned_by 5), X is CWUser', [{'X': 'CWUser'}])],
  1357                       ('FetchStep', [('Any X WHERE EXISTS(X owned_by %s), X is CWUser' % ueid, [{'X': 'CWUser'}])],
  1335                        [self.system], {'X': 'table1.C0'}, {'X': 'table0.C0'}, [])]),
  1358                        [self.system], {'X': 'table1.C0'}, {'X': 'table0.C0'}, [])]),
  1336                     ('OneFetchStep', [('Any X ORDERBY FTIRANK(X) WHERE X has_text "bla"',
  1359                     ('OneFetchStep', [('Any X ORDERBY FTIRANK(X) WHERE X has_text "bla"',
  1337                                        [{'X': 'CWUser'}, {'X': 'Personne'}])],
  1360                                        [{'X': 'CWUser'}, {'X': 'Personne'}])],
  1338                      None, None, [self.system], {'X': 'table0.C0'}, []),
  1361                      None, None, [self.system], {'X': 'table0.C0'}, []),
  1339                     ])
  1362                     ])
  1352                     ])
  1375                     ])
  1353 
  1376 
  1354     def test_security_has_text_select_rank(self):
  1377     def test_security_has_text_select_rank(self):
  1355         # use a guest user
  1378         # use a guest user
  1356         self.session = self.user_groups_session('guests')
  1379         self.session = self.user_groups_session('guests')
       
  1380         ueid = self.session.user.eid
  1357         self._test('Any X, FTIRANK(X) WHERE X has_text "bla", X firstname "bla"',
  1381         self._test('Any X, FTIRANK(X) WHERE X has_text "bla", X firstname "bla"',
  1358                    [('FetchStep', [('Any X,X WHERE X firstname "bla", X is CWUser', [{'X': 'CWUser'}])],
  1382                    [('FetchStep', [('Any X,X WHERE X firstname "bla", X is CWUser', [{'X': 'CWUser'}])],
  1359                      [self.ldap, self.system], None, {'X': 'table0.C1'}, []),
  1383                      [self.ldap, self.system], None, {'X': 'table0.C1'}, []),
  1360                     ('UnionStep', None, None, [
  1384                     ('UnionStep', None, None, [
  1361                         ('OneFetchStep', [('Any X,FTIRANK(X) WHERE X has_text "bla", EXISTS(X owned_by 5), X is CWUser', [{'X': 'CWUser'}])],
  1385                         ('OneFetchStep', [('Any X,FTIRANK(X) WHERE X has_text "bla", EXISTS(X owned_by %s), X is CWUser' % ueid, [{'X': 'CWUser'}])],
  1362                          None, None, [self.system], {'X': 'table0.C1'}, []),
  1386                          None, None, [self.system], {'X': 'table0.C1'}, []),
  1363                         ('OneFetchStep', [('Any X,FTIRANK(X) WHERE X has_text "bla", X firstname "bla", X is Personne', [{'X': 'Personne'}])],
  1387                         ('OneFetchStep', [('Any X,FTIRANK(X) WHERE X has_text "bla", X firstname "bla", X is Personne', [{'X': 'Personne'}])],
  1364                          None, None, [self.system], {}, []),
  1388                          None, None, [self.system], {}, []),
  1365                         ]),
  1389                         ]),
  1366                     ])
  1390                     ])
  1434                      [self.system],
  1458                      [self.system],
  1435                      {'D': 'table0.C1', 'Y': 'table0.C0', 'Y.creation_date': 'table0.C1'}, [])
  1459                      {'D': 'table0.C1', 'Y': 'table0.C0', 'Y.creation_date': 'table0.C1'}, [])
  1436                    ])
  1460                    ])
  1437 
  1461 
  1438     def test_subquery_1(self):
  1462     def test_subquery_1(self):
       
  1463         ueid = self.session.user.eid
  1439         self._test('DISTINCT Any B,C ORDERBY C WHERE A created_by B, B login C, EXISTS(B owned_by D), D eid %(E)s '
  1464         self._test('DISTINCT Any B,C ORDERBY C WHERE A created_by B, B login C, EXISTS(B owned_by D), D eid %(E)s '
  1440                    'WITH A,N BEING ((Any X,N WHERE X is Tag, X name N) UNION (Any X,T WHERE X is Bookmark, X title T))',
  1465                    'WITH A,N BEING ((Any X,N WHERE X is Tag, X name N) UNION (Any X,T WHERE X is Bookmark, X title T))',
  1441                    [('FetchStep', [('Any X,N WHERE X is Tag, X name N', [{'N': 'String', 'X': 'Tag'}]),
  1466                    [('FetchStep', [('Any X,N WHERE X is Tag, X name N', [{'N': 'String', 'X': 'Tag'}]),
  1442                                    ('Any X,T WHERE X is Bookmark, X title T',
  1467                                    ('Any X,T WHERE X is Bookmark, X title T',
  1443                                     [{'T': 'String', 'X': 'Bookmark'}])],
  1468                                     [{'T': 'String', 'X': 'Bookmark'}])],
  1444                      [self.system], {}, {'N': 'table0.C1', 'X': 'table0.C0', 'X.name': 'table0.C1'}, []),
  1469                      [self.system], {}, {'N': 'table0.C1', 'X': 'table0.C0', 'X.name': 'table0.C1'}, []),
  1445                     ('FetchStep',
  1470                     ('FetchStep',
  1446                      [('Any B,C WHERE B login C, B is CWUser', [{'B': 'CWUser', 'C': 'String'}])],
  1471                      [('Any B,C WHERE B login C, B is CWUser', [{'B': 'CWUser', 'C': 'String'}])],
  1447                      [self.ldap, self.system], None, {'B': 'table1.C0', 'B.login': 'table1.C1', 'C': 'table1.C1'}, []),
  1472                      [self.ldap, self.system], None, {'B': 'table1.C0', 'B.login': 'table1.C1', 'C': 'table1.C1'}, []),
  1448                     ('OneFetchStep', [('DISTINCT Any B,C ORDERBY C WHERE A created_by B, B login C, EXISTS(B owned_by 5), B is CWUser, A is IN(Bookmark, Tag)',
  1473                     ('OneFetchStep', [('DISTINCT Any B,C ORDERBY C WHERE A created_by B, B login C, EXISTS(B owned_by %s), B is CWUser, A is IN(Bookmark, Tag)' % ueid,
  1449                                        [{'A': 'Bookmark', 'B': 'CWUser', 'C': 'String'},
  1474                                        [{'A': 'Bookmark', 'B': 'CWUser', 'C': 'String'},
  1450                                         {'A': 'Tag', 'B': 'CWUser', 'C': 'String'}])],
  1475                                         {'A': 'Tag', 'B': 'CWUser', 'C': 'String'}])],
  1451                      None, None, [self.system],
  1476                      None, None, [self.system],
  1452                      {'A': 'table0.C0',
  1477                      {'A': 'table0.C0',
  1453                       'B': 'table1.C0', 'B.login': 'table1.C1',
  1478                       'B': 'table1.C0', 'B.login': 'table1.C1',
  1454                       'C': 'table1.C1',
  1479                       'C': 'table1.C1',
  1455                       'N': 'table0.C1'},
  1480                       'N': 'table0.C1'},
  1456                      [])],
  1481                      [])],
  1457                    {'E': self.session.user.eid})
  1482                    {'E': ueid})
  1458 
  1483 
  1459     def test_subquery_2(self):
  1484     def test_subquery_2(self):
       
  1485         ueid = self.session.user.eid
  1460         self._test('DISTINCT Any B,C ORDERBY C WHERE A created_by B, B login C, EXISTS(B owned_by D), D eid %(E)s '
  1486         self._test('DISTINCT Any B,C ORDERBY C WHERE A created_by B, B login C, EXISTS(B owned_by D), D eid %(E)s '
  1461                    'WITH A,N BEING ((Any X,N WHERE X is Tag, X name N) UNION (Any X,T WHERE X is Card, X title T))',
  1487                    'WITH A,N BEING ((Any X,N WHERE X is Tag, X name N) UNION (Any X,T WHERE X is Card, X title T))',
  1462                    [('UnionFetchStep',
  1488                    [('UnionFetchStep',
  1463                      [('FetchStep', [('Any X,N WHERE X is Tag, X name N', [{'N': 'String', 'X': 'Tag'}])],
  1489                      [('FetchStep', [('Any X,N WHERE X is Tag, X name N', [{'N': 'String', 'X': 'Tag'}])],
  1464                        [self.system], {},
  1490                        [self.system], {},
  1477                         'X.title': 'table0.C1'}, []),
  1503                         'X.title': 'table0.C1'}, []),
  1478                       ]),
  1504                       ]),
  1479                     ('FetchStep',
  1505                     ('FetchStep',
  1480                      [('Any B,C WHERE B login C, B is CWUser', [{'B': 'CWUser', 'C': 'String'}])],
  1506                      [('Any B,C WHERE B login C, B is CWUser', [{'B': 'CWUser', 'C': 'String'}])],
  1481                      [self.ldap, self.system], None, {'B': 'table1.C0', 'B.login': 'table1.C1', 'C': 'table1.C1'}, []),
  1507                      [self.ldap, self.system], None, {'B': 'table1.C0', 'B.login': 'table1.C1', 'C': 'table1.C1'}, []),
  1482                     ('OneFetchStep', [('DISTINCT Any B,C ORDERBY C WHERE A created_by B, B login C, EXISTS(B owned_by 5), B is CWUser, A is IN(Card, Tag)',
  1508                     ('OneFetchStep', [('DISTINCT Any B,C ORDERBY C WHERE A created_by B, B login C, EXISTS(B owned_by %s), B is CWUser, A is IN(Card, Tag)' % ueid,
  1483                                        [{'A': 'Card', 'B': 'CWUser', 'C': 'String'},
  1509                                        [{'A': 'Card', 'B': 'CWUser', 'C': 'String'},
  1484                                         {'A': 'Tag', 'B': 'CWUser', 'C': 'String'}])],
  1510                                         {'A': 'Tag', 'B': 'CWUser', 'C': 'String'}])],
  1485                      None, None, [self.system],
  1511                      None, None, [self.system],
  1486                      {'A': 'table0.C0',
  1512                      {'A': 'table0.C0',
  1487                       'B': 'table1.C0', 'B.login': 'table1.C1',
  1513                       'B': 'table1.C0', 'B.login': 'table1.C1',
  1488                       'C': 'table1.C1',
  1514                       'C': 'table1.C1',
  1489                       'N': 'table0.C1'},
  1515                       'N': 'table0.C1'},
  1490                      [])],
  1516                      [])],
  1491                    {'E': self.session.user.eid})
  1517                    {'E': ueid})
  1492 
  1518 
  1493     def test_eid_dont_cross_relation_1(self):
  1519     def test_eid_dont_cross_relation_1(self):
  1494         repo._type_source_cache[999999] = ('Personne', 'system', 999999)
  1520         repo._type_source_cache[999999] = ('Personne', 'system', 999999)
  1495         self._test('Any Y,YT WHERE X eid %(x)s, X fiche Y, Y title YT',
  1521         self._test('Any Y,YT WHERE X eid %(x)s, X fiche Y, Y title YT',
  1496                    [('OneFetchStep', [('Any Y,YT WHERE X eid 999999, X fiche Y, Y title YT',
  1522                    [('OneFetchStep', [('Any Y,YT WHERE X eid 999999, X fiche Y, Y title YT',
  1660 
  1686 
  1661     def test_delete_relation1(self):
  1687     def test_delete_relation1(self):
  1662         ueid = self.session.user.eid
  1688         ueid = self.session.user.eid
  1663         self._test('DELETE X created_by Y WHERE X eid %(x)s, NOT Y eid %(y)s',
  1689         self._test('DELETE X created_by Y WHERE X eid %(x)s, NOT Y eid %(y)s',
  1664                    [('DeleteRelationsStep', [
  1690                    [('DeleteRelationsStep', [
  1665                        ('OneFetchStep', [('Any 5,Y WHERE %s created_by Y, NOT Y eid %s, Y is CWUser'%(ueid, ueid),
  1691                        ('OneFetchStep', [('Any %s,Y WHERE %s created_by Y, NOT Y eid %s, Y is CWUser' % (ueid, ueid, ueid),
  1666                                           [{'Y': 'CWUser'}])],
  1692                                           [{'Y': 'CWUser'}])],
  1667                         None, None, [self.system], {}, []),
  1693                         None, None, [self.system], {}, []),
  1668                        ]),
  1694                        ]),
  1669                     ],
  1695                     ],
  1670                    {'x': ueid, 'y': ueid})
  1696                    {'x': ueid, 'y': ueid})
  1777                        {'x': 999999})
  1803                        {'x': 999999})
  1778         finally:
  1804         finally:
  1779             self.cards.dont_cross_relations.remove('created_by')
  1805             self.cards.dont_cross_relations.remove('created_by')
  1780 
  1806 
  1781     def test_ambigous_cross_relation(self):
  1807     def test_ambigous_cross_relation(self):
       
  1808         self.repo._type_source_cache[999999] = ('Note', 'cards', 999999)
       
  1809         self.cards.support_relations['see_also'] = True
       
  1810         self.cards.cross_relations.add('see_also')
       
  1811         try:
       
  1812             self._test('Any X,AA ORDERBY AA WHERE E eid %(x)s, E see_also X, X modification_date AA',
       
  1813                        [('AggrStep',
       
  1814                          'SELECT table0.C0, table0.C1 FROM table0 ORDER BY table0.C1',
       
  1815                          None,
       
  1816                          [('FetchStep',
       
  1817                            [('Any X,AA WHERE 999999 see_also X, X modification_date AA, X is Note',
       
  1818                              [{'AA': 'Datetime', 'X': 'Note'}])], [self.cards, self.system], {},
       
  1819                            {'AA': 'table0.C1', 'X': 'table0.C0',
       
  1820                             'X.modification_date': 'table0.C1'},
       
  1821                            []),
       
  1822                           ('FetchStep',
       
  1823                            [('Any X,AA WHERE 999999 see_also X, X modification_date AA, X is Bookmark',
       
  1824                              [{'AA': 'Datetime', 'X': 'Bookmark'}])],
       
  1825                            [self.system], {},
       
  1826                            {'AA': 'table0.C1', 'X': 'table0.C0',
       
  1827                             'X.modification_date': 'table0.C1'},
       
  1828                            [])])],
       
  1829                          {'x': 999999})
       
  1830         finally:
       
  1831             del self.cards.support_relations['see_also']
       
  1832             self.cards.cross_relations.remove('see_also')
       
  1833 
       
  1834     def test_state_of_cross(self):
       
  1835         self._test('DELETE State X WHERE NOT X state_of Y',
       
  1836                    [('DeleteEntitiesStep',
       
  1837                      [('OneFetchStep',
       
  1838                        [('Any X WHERE NOT X state_of Y, X is State, Y is Workflow',
       
  1839                          [{'X': 'State', 'Y': 'Workflow'}])],
       
  1840                        None, None, [self.system], {}, [])])]
       
  1841                    )
       
  1842 
       
  1843 
       
  1844     def test_source_specified_0_0(self):
       
  1845         self._test('Card X WHERE X cw_source S, S eid 1',
       
  1846                    [('OneFetchStep', [('Any X WHERE X is Card',
       
  1847                                        [{'X': 'Card'}])],
       
  1848                      None, None,
       
  1849                      [self.system],{}, [])
       
  1850                     ])
       
  1851 
       
  1852     def test_source_specified_0_1(self):
       
  1853         self._test('Any X, S WHERE X is Card, X cw_source S, S eid 1',
       
  1854                    [('OneFetchStep', [('Any X,1 WHERE X is Card',
       
  1855                                        [{'X': 'Card'}])],
       
  1856                      None, None,
       
  1857                      [self.system],{}, [])
       
  1858                     ])
       
  1859 
       
  1860     def test_source_specified_1_0(self):
       
  1861         self._test('Card X WHERE X cw_source S, S name "system"',
       
  1862                    [('OneFetchStep', [('Any X WHERE X is Card',
       
  1863                                        [{'X': 'Card'}])],
       
  1864                      None, None,
       
  1865                      [self.system],{}, [])
       
  1866                     ])
       
  1867 
       
  1868     def test_source_specified_1_1(self):
       
  1869         self._test('Any X, SN WHERE X is Card, X cw_source S, S name "system", S name SN',
       
  1870                    [('OneFetchStep', [('Any X,SN WHERE X is Card, X cw_source S, S name "system", '
       
  1871                                        'S name SN',
       
  1872                                        [{'S': 'CWSource', 'SN': 'String', 'X': 'Card'}])],
       
  1873                      None, None, [self.system], {}, [])
       
  1874                     ])
       
  1875 
       
  1876     def test_source_specified_2_0(self):
       
  1877         self._test('Card X WHERE X cw_source S, NOT S eid 1',
       
  1878                    [('OneFetchStep', [('Any X WHERE X is Card',
       
  1879                                        [{'X': 'Card'}])],
       
  1880                      None, None,
       
  1881                      [self.cards],{}, [])
       
  1882                     ])
       
  1883         self._test('Card X WHERE NOT X cw_source S, S eid 1',
       
  1884                    [('OneFetchStep', [('Any X WHERE X is Card',
       
  1885                                        [{'X': 'Card'}])],
       
  1886                      None, None,
       
  1887                      [self.cards],{}, [])
       
  1888                     ])
       
  1889 
       
  1890     def test_source_specified_2_1(self):
       
  1891         self._test('Card X WHERE X cw_source S, NOT S name "system"',
       
  1892                    [('OneFetchStep', [('Any X WHERE X is Card',
       
  1893                                        [{'X': 'Card'}])],
       
  1894                      None, None,
       
  1895                      [self.cards],{}, [])
       
  1896                     ])
       
  1897         self._test('Card X WHERE NOT X cw_source S, S name "system"',
       
  1898                    [('OneFetchStep', [('Any X WHERE X is Card',
       
  1899                                        [{'X': 'Card'}])],
       
  1900                      None, None,
       
  1901                      [self.cards],{}, [])
       
  1902                     ])
       
  1903 
       
  1904     def test_source_conflict_1(self):
       
  1905         self.repo._type_source_cache[999999] = ('Note', 'cards', 999999)
       
  1906         ex = self.assertRaises(BadRQLQuery,
       
  1907                                self._test, 'Any X WHERE X cw_source S, S name "system", X eid %(x)s',
       
  1908                                [], {'x': 999999})
       
  1909         self.assertEqual(str(ex), 'source conflict for term %(x)s')
       
  1910 
       
  1911     def test_source_conflict_2(self):
       
  1912         ex = self.assertRaises(BadRQLQuery,
       
  1913                                self._test, 'Card X WHERE X cw_source S, S name "systeme"', [])
       
  1914         self.assertEqual(str(ex), 'source conflict for term X')
       
  1915 
       
  1916     def test_source_conflict_3(self):
       
  1917         ex = self.assertRaises(BadRQLQuery,
       
  1918                                self._test, 'CWSource X WHERE X cw_source S, S name "cards"', [])
       
  1919         self.assertEqual(str(ex), 'source conflict for term X')
       
  1920 
       
  1921     def test_ambigous_cross_relation_source_specified(self):
  1782         self.repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1922         self.repo._type_source_cache[999999] = ('Note', 'cards', 999999)
  1783         self.cards.support_relations['see_also'] = True
  1923         self.cards.support_relations['see_also'] = True
  1784         self.cards.cross_relations.add('see_also')
  1924         self.cards.cross_relations.add('see_also')
  1785         try:
  1925         try:
  1786             self._test('Any X,AA ORDERBY AA WHERE E eid %(x)s, E see_also X, X modification_date AA',
  1926             self._test('Any X,AA ORDERBY AA WHERE E eid %(x)s, E see_also X, X modification_date AA',
  1862                                        [{'P': 'Bookmark', 'U': 'CWUser', 'X': 'CWEType', 'CD': 'Datetime'}])],
  2002                                        [{'P': 'Bookmark', 'U': 'CWUser', 'X': 'CWEType', 'CD': 'Datetime'}])],
  1863                      5, None,  [self.system], {'U': 'table0.C0'}, [])]
  2003                      5, None,  [self.system], {'U': 'table0.C0'}, [])]
  1864                    )
  2004                    )
  1865 
  2005 
  1866     def test_nonregr4(self):
  2006     def test_nonregr4(self):
       
  2007         ueid = self.session.user.eid
  1867         self._test('Any U ORDERBY D DESC WHERE WF wf_info_for X, WF creation_date D, WF from_state FS, '
  2008         self._test('Any U ORDERBY D DESC WHERE WF wf_info_for X, WF creation_date D, WF from_state FS, '
  1868                    'WF owned_by U?, X eid %(x)s',
  2009                    'WF owned_by U?, X eid %(x)s',
  1869                    [#('FetchStep', [('Any U WHERE U is CWUser', [{'U': 'CWUser'}])],
  2010                    [#('FetchStep', [('Any U WHERE U is CWUser', [{'U': 'CWUser'}])],
  1870                     # [self.ldap, self.system], None, {'U': 'table0.C0'}, []),
  2011                     # [self.ldap, self.system], None, {'U': 'table0.C0'}, []),
  1871                     ('OneFetchStep', [('Any U ORDERBY D DESC WHERE WF wf_info_for 5, WF creation_date D, WF from_state FS, WF owned_by U?',
  2012                     ('OneFetchStep', [('Any U ORDERBY D DESC WHERE WF wf_info_for %s, WF creation_date D, WF from_state FS, WF owned_by U?' % ueid,
  1872                                        [{'WF': 'TrInfo', 'FS': 'State', 'U': 'CWUser', 'D': 'Datetime'}])],
  2013                                        [{'WF': 'TrInfo', 'FS': 'State', 'U': 'CWUser', 'D': 'Datetime'}])],
  1873                      None, None,
  2014                      None, None,
  1874                      [self.system], {}, [])],
  2015                      [self.system], {}, [])],
  1875                    {'x': self.session.user.eid})
  2016                    {'x': ueid})
  1876 
  2017 
  1877     def test_nonregr5(self):
  2018     def test_nonregr5(self):
  1878         # original jpl query:
  2019         # original jpl query:
  1879         # DISTINCT Version V WHERE MB done_in MV, MV eid %(x)s,
  2020         # DISTINCT Version V WHERE MB done_in MV, MV eid %(x)s,
  1880         # MB depends_on B, B done_in V, V version_of P, NOT P eid %(p)s'
  2021         # MB depends_on B, B done_in V, V version_of P, NOT P eid %(p)s'
  1995                        [])]
  2136                        [])]
  1996                       )],
  2137                       )],
  1997                    {'x': 999999})
  2138                    {'x': 999999})
  1998 
  2139 
  1999     def test_nonregr13_1(self):
  2140     def test_nonregr13_1(self):
       
  2141         ueid = self.session.user.eid
  2000         # identity wrapped into exists:
  2142         # identity wrapped into exists:
  2001         # should'nt propagate constraint that U is in the same source as ME
  2143         # should'nt propagate constraint that U is in the same source as ME
  2002         self._test('Any B,U,UL GROUPBY B,U,UL WHERE B created_by U?, B is File '
  2144         self._test('Any B,U,UL GROUPBY B,U,UL WHERE B created_by U?, B is File '
  2003                    'WITH U,UL BEING (Any U,UL WHERE ME eid %(x)s, (EXISTS(U identity ME) '
  2145                    'WITH U,UL BEING (Any U,UL WHERE ME eid %(x)s, (EXISTS(U identity ME) '
  2004                    'OR (EXISTS(U in_group G, G name IN("managers", "staff")))) '
  2146                    'OR (EXISTS(U in_group G, G name IN("managers", "staff")))) '
  2006                    [('FetchStep', [('Any U,UL WHERE U login UL, U is CWUser',
  2148                    [('FetchStep', [('Any U,UL WHERE U login UL, U is CWUser',
  2007                                     [{'U': 'CWUser', 'UL': 'String'}])],
  2149                                     [{'U': 'CWUser', 'UL': 'String'}])],
  2008                      [self.ldap, self.system], None,
  2150                      [self.ldap, self.system], None,
  2009                      {'U': 'table0.C0', 'U.login': 'table0.C1', 'UL': 'table0.C1'},
  2151                      {'U': 'table0.C0', 'U.login': 'table0.C1', 'UL': 'table0.C1'},
  2010                      []),
  2152                      []),
  2011                     ('FetchStep', [('Any U,UL WHERE ((EXISTS(U identity 5)) OR (EXISTS(U in_group G, G name IN("managers", "staff"), G is CWGroup))) OR (EXISTS(U in_group H, 5 in_group H, NOT H name "users", H is CWGroup)), U login UL, U is CWUser',
  2153                     ('FetchStep', [('Any U,UL WHERE ((EXISTS(U identity %s)) OR (EXISTS(U in_group G, G name IN("managers", "staff"), G is CWGroup))) OR (EXISTS(U in_group H, %s in_group H, NOT H name "users", H is CWGroup)), U login UL, U is CWUser' % (ueid, ueid),
  2012                                     [{'G': 'CWGroup', 'H': 'CWGroup', 'U': 'CWUser', 'UL': 'String'}])],
  2154                                     [{'G': 'CWGroup', 'H': 'CWGroup', 'U': 'CWUser', 'UL': 'String'}])],
  2013                      [self.system],
  2155                      [self.system],
  2014                      {'U': 'table0.C0', 'U.login': 'table0.C1', 'UL': 'table0.C1'},
  2156                      {'U': 'table0.C0', 'U.login': 'table0.C1', 'UL': 'table0.C1'},
  2015                      {'U': 'table1.C0', 'U.login': 'table1.C1', 'UL': 'table1.C1'},
  2157                      {'U': 'table1.C0', 'U.login': 'table1.C1', 'UL': 'table1.C1'},
  2016                      []),
  2158                      []),
  2017                     ('OneFetchStep', [('Any B,U,UL GROUPBY B,U,UL WHERE B created_by U?, B is File',
  2159                     ('OneFetchStep', [('Any B,U,UL GROUPBY B,U,UL WHERE B created_by U?, B is File',
  2018                                        [{'B': 'File', 'U': 'CWUser', 'UL': 'String'}])],
  2160                                        [{'B': 'File', 'U': 'CWUser', 'UL': 'String'}])],
  2019                      None, None, [self.system],
  2161                      None, None, [self.system],
  2020                      {'U': 'table1.C0', 'UL': 'table1.C1'},
  2162                      {'U': 'table1.C0', 'UL': 'table1.C1'},
  2021                      [])],
  2163                      [])],
  2022                    {'x': self.session.user.eid})
  2164                    {'x': ueid})
  2023 
  2165 
  2024     def test_nonregr13_2(self):
  2166     def test_nonregr13_2(self):
  2025         # identity *not* wrapped into exists.
  2167         # identity *not* wrapped into exists.
  2026         #
  2168         #
  2027         # XXX this test fail since in this case, in "U identity 5" U and 5 are
  2169         # XXX this test fail since in this case, in "U identity 5" U and 5 are
  2031         # IMO this is normal, unless we introduce a special case for the
  2173         # IMO this is normal, unless we introduce a special case for the
  2032         # identity relation. BUT I think it's better to leave it as is and to
  2174         # identity relation. BUT I think it's better to leave it as is and to
  2033         # explain constraint propagation rules, and so why this should be
  2175         # explain constraint propagation rules, and so why this should be
  2034         # wrapped in exists() if used in multi-source
  2176         # wrapped in exists() if used in multi-source
  2035         self.skipTest('take a look at me if you wish')
  2177         self.skipTest('take a look at me if you wish')
       
  2178         ueid = self.session.user.eid
  2036         self._test('Any B,U,UL GROUPBY B,U,UL WHERE B created_by U?, B is File '
  2179         self._test('Any B,U,UL GROUPBY B,U,UL WHERE B created_by U?, B is File '
  2037                    'WITH U,UL BEING (Any U,UL WHERE ME eid %(x)s, (U identity ME '
  2180                    'WITH U,UL BEING (Any U,UL WHERE ME eid %(x)s, (U identity ME '
  2038                    'OR (EXISTS(U in_group G, G name IN("managers", "staff")))) '
  2181                    'OR (EXISTS(U in_group G, G name IN("managers", "staff")))) '
  2039                    'OR (EXISTS(U in_group H, ME in_group H, NOT H name "users")), U login UL, U is CWUser)',
  2182                    'OR (EXISTS(U in_group H, ME in_group H, NOT H name "users")), U login UL, U is CWUser)',
  2040                    [('FetchStep', [('Any U,UL WHERE U login UL, U is CWUser',
  2183                    [('FetchStep', [('Any U,UL WHERE U login UL, U is CWUser',
  2041                                     [{'U': 'CWUser', 'UL': 'String'}])],
  2184                                     [{'U': 'CWUser', 'UL': 'String'}])],
  2042                      [self.ldap, self.system], None,
  2185                      [self.ldap, self.system], None,
  2043                      {'U': 'table0.C0', 'U.login': 'table0.C1', 'UL': 'table0.C1'},
  2186                      {'U': 'table0.C0', 'U.login': 'table0.C1', 'UL': 'table0.C1'},
  2044                      []),
  2187                      []),
  2045                     ('FetchStep', [('Any U,UL WHERE ((U identity 5) OR (EXISTS(U in_group G, G name IN("managers", "staff"), G is CWGroup))) OR (EXISTS(U in_group H, 5 in_group H, NOT H name "users", H is CWGroup)), U login UL, U is CWUser',
  2188                     ('FetchStep', [('Any U,UL WHERE ((U identity %s) OR (EXISTS(U in_group G, G name IN("managers", "staff"), G is CWGroup))) OR (EXISTS(U in_group H, %s in_group H, NOT H name "users", H is CWGroup)), U login UL, U is CWUser' % (ueid, ueid),
  2046                                     [{'G': 'CWGroup', 'H': 'CWGroup', 'U': 'CWUser', 'UL': 'String'}])],
  2189                                     [{'G': 'CWGroup', 'H': 'CWGroup', 'U': 'CWUser', 'UL': 'String'}])],
  2047                      [self.system],
  2190                      [self.system],
  2048                      {'U': 'table0.C0', 'U.login': 'table0.C1', 'UL': 'table0.C1'},
  2191                      {'U': 'table0.C0', 'U.login': 'table0.C1', 'UL': 'table0.C1'},
  2049                      {'U': 'table1.C0', 'U.login': 'table1.C1', 'UL': 'table1.C1'},
  2192                      {'U': 'table1.C0', 'U.login': 'table1.C1', 'UL': 'table1.C1'},
  2050                      []),
  2193                      []),
  2092                    [('OneFetchStep', [('Any 999999 WHERE O use_email 999999, ((EXISTS(O identity 999998)) OR (EXISTS(O in_group G, G name IN("managers", "staff")))) OR (EXISTS(O in_group G2, 999998 in_group G2, NOT G2 name "users"))',
  2235                    [('OneFetchStep', [('Any 999999 WHERE O use_email 999999, ((EXISTS(O identity 999998)) OR (EXISTS(O in_group G, G name IN("managers", "staff")))) OR (EXISTS(O in_group G2, 999998 in_group G2, NOT G2 name "users"))',
  2093                                        [{'G': 'CWGroup', 'G2': 'CWGroup', 'O': 'CWUser'}])],
  2236                                        [{'G': 'CWGroup', 'G2': 'CWGroup', 'O': 'CWUser'}])],
  2094                      None, None, [self.system], {}, [])],
  2237                      None, None, [self.system], {}, [])],
  2095                    {'x': 999999, 'u': 999998})
  2238                    {'x': 999999, 'u': 999998})
  2096 
  2239 
  2097     def test_state_of_cross(self):
       
  2098         self._test('DELETE State X WHERE NOT X state_of Y',
       
  2099                    [('DeleteEntitiesStep',
       
  2100                      [('OneFetchStep',
       
  2101                        [('Any X WHERE NOT X state_of Y, X is State, Y is Workflow',
       
  2102                          [{'X': 'State', 'Y': 'Workflow'}])],
       
  2103                        None, None, [self.system], {}, [])])]
       
  2104                    )
       
  2105 
  2240 
  2106 class MSPlannerTwoSameExternalSourcesTC(BasePlannerTC):
  2241 class MSPlannerTwoSameExternalSourcesTC(BasePlannerTC):
  2107     """test planner related feature on a 3-sources repository:
  2242     """test planner related feature on a 3-sources repository:
  2108 
  2243 
  2109     * 2 rql sources supporting Card
  2244     * 2 rql sources supporting Card
  2255                                     [{'X': 'Note'}, {'X': 'State'}, {'X': 'Card'}])],
  2390                                     [{'X': 'Note'}, {'X': 'State'}, {'X': 'Card'}])],
  2256                      [self.cards, self.cards2, self.system],
  2391                      [self.cards, self.cards2, self.system],
  2257                      None, {'X': 'table0.C0'}, []),
  2392                      None, {'X': 'table0.C0'}, []),
  2258                     ('UnionStep', None, None,
  2393                     ('UnionStep', None, None,
  2259                      [('OneFetchStep',
  2394                      [('OneFetchStep',
  2260                        [(u'Any X WHERE X owned_by U, U login "anon", U is CWUser, X is IN(Affaire, BaseTransition, Basket, Bookmark, CWAttribute, CWCache, CWConstraint, CWConstraintType, CWEType, CWGroup, CWPermission, CWProperty, CWRType, CWRelation, CWUniqueTogetherConstraint, CWUser, Division, Email, EmailAddress, EmailPart, EmailThread, ExternalUri, File, Folder, Personne, RQLExpression, Societe, SubDivision, SubWorkflowExitPoint, Tag, TrInfo, Transition, Workflow, WorkflowTransition)',
  2395                        [(u'Any X WHERE X owned_by U, U login "anon", U is CWUser, X is IN(Affaire, BaseTransition, Basket, Bookmark, CWAttribute, CWCache, CWConstraint, CWConstraintType, CWEType, CWGroup, CWPermission, CWProperty, CWRType, CWRelation, CWSource, CWSourceHostConfig, CWUniqueTogetherConstraint, CWUser, Division, Email, EmailAddress, EmailPart, EmailThread, ExternalUri, File, Folder, Personne, RQLExpression, Societe, SubDivision, SubWorkflowExitPoint, Tag, TrInfo, Transition, Workflow, WorkflowTransition)',
  2261                          [{'U': 'CWUser', 'X': 'Affaire'},
  2396                          [{'U': 'CWUser', 'X': 'Affaire'},
  2262                           {'U': 'CWUser', 'X': 'BaseTransition'},
  2397                           {'U': 'CWUser', 'X': 'BaseTransition'},
  2263                           {'U': 'CWUser', 'X': 'Basket'},
  2398                           {'U': 'CWUser', 'X': 'Basket'},
  2264                           {'U': 'CWUser', 'X': 'Bookmark'},
  2399                           {'U': 'CWUser', 'X': 'Bookmark'},
  2265                           {'U': 'CWUser', 'X': 'CWAttribute'},
  2400                           {'U': 'CWUser', 'X': 'CWAttribute'},
  2270                           {'U': 'CWUser', 'X': 'CWGroup'},
  2405                           {'U': 'CWUser', 'X': 'CWGroup'},
  2271                           {'U': 'CWUser', 'X': 'CWPermission'},
  2406                           {'U': 'CWUser', 'X': 'CWPermission'},
  2272                           {'U': 'CWUser', 'X': 'CWProperty'},
  2407                           {'U': 'CWUser', 'X': 'CWProperty'},
  2273                           {'U': 'CWUser', 'X': 'CWRType'},
  2408                           {'U': 'CWUser', 'X': 'CWRType'},
  2274                           {'U': 'CWUser', 'X': 'CWRelation'},
  2409                           {'U': 'CWUser', 'X': 'CWRelation'},
       
  2410                           {'U': 'CWUser', 'X': 'CWSource'},
       
  2411                           {'U': 'CWUser', 'X': 'CWSourceHostConfig'},
  2275                           {'U': 'CWUser', 'X': 'CWUniqueTogetherConstraint'},
  2412                           {'U': 'CWUser', 'X': 'CWUniqueTogetherConstraint'},
  2276                           {'U': 'CWUser', 'X': 'CWUser'},
  2413                           {'U': 'CWUser', 'X': 'CWUser'},
  2277                           {'U': 'CWUser', 'X': 'Division'},
  2414                           {'U': 'CWUser', 'X': 'Division'},
  2278                           {'U': 'CWUser', 'X': 'Email'},
  2415                           {'U': 'CWUser', 'X': 'Email'},
  2279                           {'U': 'CWUser', 'X': 'EmailAddress'},
  2416                           {'U': 'CWUser', 'X': 'EmailAddress'},