[entity vocabulary] fix unrelated rql generation to skip rql constraints that don't make sense
--- a/entity.py Thu Mar 31 15:23:46 2011 +0200
+++ b/entity.py Thu Mar 31 15:23:50 2011 +0200
@@ -165,6 +165,7 @@
selection = [mainvar]
orderby = []
# start from 26 to avoid possible conflicts with X
+ # XXX not enough to be sure it'll be no conflicts
varmaker = rqlvar_maker(index=26)
cls._fetch_restrictions(mainvar, varmaker, fetchattrs, selection,
orderby, restrictions, user, ordermethod)
@@ -768,29 +769,38 @@
else:
searchedvar, evar = 'S', 'O'
objtype, subjtype = self.e_schema, targettype
+ rdef = rtype.role_rdef(self.e_schema, targettype, role)
if self.has_eid():
- restriction = ['NOT S %s O' % rtype, '%s eid %%(x)s' % evar]
+ restriction = ['NOT S %s O' % rtype]
+ if rdef.role_cardinality(role) not in '?1':
+ # if cardinality in '1?', don't add restriction on eid
+ restriction.append('%s eid %%(x)s' % evar)
args = {'x': self.eid}
if role == 'subject':
securitycheck_args = {'fromeid': self.eid}
else:
securitycheck_args = {'toeid': self.eid}
else:
- restriction = []
+ if rdef.role_cardinality(role) in '?1':
+ restriction = ['NOT S %s O' % rtype]
+ else:
+ restriction = []
args = {}
securitycheck_args = {}
- rdef = rtype.role_rdef(self.e_schema, targettype, role)
insertsecurity = (rdef.has_local_role('add') and not
rdef.has_perm(self._cw, 'add', **securitycheck_args))
# XXX consider constraint.mainvars to check if constraint apply
if vocabconstraints:
# RQLConstraint is a subclass for RQLVocabularyConstraint, so they
# will be included as well
- restriction += [cstr.expression for cstr in rdef.constraints
- if isinstance(cstr, RQLVocabularyConstraint)]
+ cstrcls = RQLVocabularyConstraint
else:
- restriction += [cstr.expression for cstr in rdef.constraints
- if isinstance(cstr, RQLConstraint)]
+ cstrcls = RQLConstraint
+ for cstr in rdef.constraints:
+ if isinstance(cstr, RQLVocabularyConstraint) and searchedvar in cstr.mainvars:
+ if not self.has_eid() and evar in cstr.mainvars:
+ continue
+ restriction.append(cstr.expression)
etypecls = self._cw.vreg['etypes'].etype_class(targettype)
rql = etypecls.fetch_rql(self._cw.user, restriction,
mainvar=searchedvar, ordermethod=ordermethod)
--- a/test/data/schema.py Thu Mar 31 15:23:46 2011 +0200
+++ b/test/data/schema.py Thu Mar 31 15:23:50 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of CubicWeb.
@@ -15,13 +15,11 @@
#
# You should have received a copy of the GNU Lesser General Public License along
# with CubicWeb. If not, see <http://www.gnu.org/licenses/>.
-"""
-
-"""
from yams.buildobjs import (EntityType, String, SubjectRelation,
RelationDefinition)
-from cubicweb.schema import WorkflowableEntityType
+from cubicweb.schema import (WorkflowableEntityType,
+ RQLConstraint, RQLVocabularyConstraint)
class Personne(EntityType):
nom = String(required=True)
@@ -29,7 +27,11 @@
type = String()
travaille = SubjectRelation('Societe')
evaluee = SubjectRelation(('Note', 'Personne'))
- connait = SubjectRelation('Personne', symmetric=True)
+ connait = SubjectRelation(
+ 'Personne', symmetric=True,
+ constraints=[
+ RQLConstraint('NOT S identity O'),
+ RQLVocabularyConstraint('NOT (S connait P, P nom "toto")')])
class Societe(EntityType):
nom = String()
--- a/test/unittest_entity.py Thu Mar 31 15:23:46 2011 +0200
+++ b/test/unittest_entity.py Thu Mar 31 15:23:50 2011 +0200
@@ -274,6 +274,33 @@
'WHERE S is CWUser, S login AA, S firstname AB, S surname AC, S modification_date AD, '
'A eid %(B)s, EXISTS(S identity A, NOT A in_group C, C name "guests", C is CWGroup)')
+ def test_unrelated_rql_constraints_creation_subject(self):
+ person = self.vreg['etypes'].etype_class('Personne')(self.request())
+ rql = person.cw_unrelated_rql('connait', 'Personne', 'subject')[0]
+ self.assertEqual(rql, 'Any O,AA,AB,AC ORDERBY AC DESC WHERE '
+ 'O is Personne, O nom AA, O prenom AB, O modification_date AC')
+
+ def test_unrelated_rql_constraints_creation_object(self):
+ person = self.vreg['etypes'].etype_class('Personne')(self.request())
+ rql = person.cw_unrelated_rql('connait', 'Personne', 'object')[0]
+ self.assertEqual(rql, 'Any S,AA,AB,AC ORDERBY AC DESC WHERE '
+ 'NOT (S connait P, P nom "toto"), S is Personne, S nom AA, '
+ 'S prenom AB, S modification_date AC')
+
+ def test_unrelated_rql_constraints_edition_subject(self):
+ person = self.request().create_entity('Personne', nom=u'sylvain')
+ rql = person.cw_unrelated_rql('connait', 'Personne', 'subject')[0]
+ self.assertEqual(rql, 'Any O,AA,AB,AC ORDERBY AC DESC WHERE '
+ 'NOT S connait O, S eid %(x)s, NOT S identity O, O is Personne, '
+ 'O nom AA, O prenom AB, O modification_date AC')
+
+ def test_unrelated_rql_constraints_edition_object(self):
+ person = self.request().create_entity('Personne', nom=u'sylvain')
+ rql = person.cw_unrelated_rql('connait', 'Personne', 'object')[0]
+ self.assertEqual(rql, 'Any S,AA,AB,AC ORDERBY AC DESC WHERE '
+ 'NOT S connait O, O eid %(x)s, NOT S identity O, NOT (S connait P, '
+ 'P nom "toto"), S is Personne, S nom AA, S prenom AB, S modification_date AC')
+
def test_unrelated_base(self):
req = self.request()
p = req.create_entity('Personne', nom=u'di mascio', prenom=u'adrien')