# HG changeset patch # User Sylvain Thénault # Date 1276157819 -7200 # Node ID 3586d36d2a45d5152ebadc5e926363ca67667e07 # Parent 30b94973bc67b6fede62d45864c7f650f6a185dc# Parent c2e8290bc7b7618f9f8545b409b2ba8199ceb8ec backport stable diff -r 30b94973bc67 -r 3586d36d2a45 __pkginfo__.py --- a/__pkginfo__.py Wed Jun 09 16:16:54 2010 +0200 +++ b/__pkginfo__.py Thu Jun 10 10:16:59 2010 +0200 @@ -42,8 +42,13 @@ __depends__ = { 'logilab-common': '>= 0.50.2', 'logilab-mtconverter': '>= 0.6.0', +<<<<<<< /home/syt/src/fcubicweb/cubicweb/__pkginfo__.py 'rql': '>= 0.26.0', 'yams': '>= 0.30.0', +======= + 'rql': '>= 0.26.2', + 'yams': '>= 0.28.1', +>>>>>>> /tmp/__pkginfo__.py~other.ZMqgs5 'docutils': '>= 0.6', #gettext # for xgettext, msgcat, etc... # web dependancies diff -r 30b94973bc67 -r 3586d36d2a45 debian/control --- a/debian/control Wed Jun 09 16:16:54 2010 +0200 +++ b/debian/control Thu Jun 10 10:16:59 2010 +0200 @@ -97,7 +97,7 @@ Package: cubicweb-common Architecture: all XB-Python-Version: ${python:Versions} -Depends: ${python:Depends}, graphviz, gettext, python-logilab-mtconverter (>= 0.6.0), python-logilab-common (>= 0.50.2), python-yams (>= 0.30.0), python-rql (>= 0.26.1), python-lxml +Depends: ${python:Depends}, graphviz, gettext, python-logilab-mtconverter (>= 0.6.0), python-logilab-common (>= 0.50.2), python-yams (>= 0.30.0), python-rql (>= 0.26.2), python-lxml Recommends: python-simpletal (>= 4.0), python-crypto Conflicts: cubicweb-core Replaces: cubicweb-core diff -r 30b94973bc67 -r 3586d36d2a45 rqlrewrite.py --- a/rqlrewrite.py Wed Jun 09 16:16:54 2010 +0200 +++ b/rqlrewrite.py Thu Jun 10 10:16:59 2010 +0200 @@ -353,7 +353,7 @@ if need_null_test: snippetrqlst = n.Or( n.make_relation(subselectvar, 'is', (None, None), n.Constant, - operator='IS'), + operator='='), snippetrqlst) subselect.add_restriction(snippetrqlst) if self.u_varname: diff -r 30b94973bc67 -r 3586d36d2a45 schema.py --- a/schema.py Wed Jun 09 16:16:54 2010 +0200 +++ b/schema.py Thu Jun 10 10:16:59 2010 +0200 @@ -852,11 +852,9 @@ except KeyError: pass rql, has_perm_defs, keyarg = self.transform_has_permission() - if creating: - # when creating an entity, consider has_*_permission satisfied - if has_perm_defs: - return True - return False + # when creating an entity, expression related to X satisfied + if creating and 'X' in self.rqlst.defined_vars: + return True if keyarg is None: kwargs.setdefault('u', session.user.eid) try: diff -r 30b94973bc67 -r 3586d36d2a45 server/session.py --- a/server/session.py Wed Jun 09 16:16:54 2010 +0200 +++ b/server/session.py Thu Jun 10 10:16:59 2010 +0200 @@ -15,9 +15,8 @@ # # You should have received a copy of the GNU Lesser General Public License along # with CubicWeb. If not, see . -"""Repository users' and internal' sessions. +"""Repository users' and internal' sessions.""" -""" from __future__ import with_statement __docformat__ = "restructuredtext en" @@ -29,7 +28,7 @@ from warnings import warn from logilab.common.deprecation import deprecated -from rql.nodes import VariableRef, Function, ETYPE_PYOBJ_MAP, etype_from_pyobj +from rql.nodes import ETYPE_PYOBJ_MAP, etype_from_pyobj from yams import BASE_TYPES from cubicweb import Binary, UnknownEid, schema @@ -49,17 +48,6 @@ NO_UNDO_TYPES.add('is_instance_of') # XXX rememberme,forgotpwd,apycot,vcsfile -def is_final(rqlst, variable, args): - # try to find if this is a final var or not - for select in rqlst.children: - for sol in select.solutions: - etype = variable.get_type(sol, args) - if etype is None: - continue - if etype in BASE_TYPES: - return True - return False - def _make_description(selected, args, solution): """return a description for a result set""" description = [] @@ -861,32 +849,37 @@ """ # not so easy, looks for variable which changes from one solution # to another - unstables = rqlst.get_variable_variables() - basedescription = [] + unstables = rqlst.get_variable_indices() + basedescr = [] todetermine = [] - selected = rqlst.children[0].selection # sample selection - for i, term in enumerate(selected): - if isinstance(term, Function) and term.descr().rtype is not None: - basedescription.append(term.get_type(term.descr().rtype, args)) - continue - for vref in term.get_nodes(VariableRef): - if vref.name in unstables: - basedescription.append(None) - todetermine.append( (i, is_final(rqlst, vref.variable, args)) ) - break + sampleselect = rqlst.children[0] + samplesols = sampleselect.solutions[0] + for i, term in enumerate(sampleselect.selection): + try: + ttype = term.get_type(samplesols, args) + except CoercionError: + ttype = None + isfinal = True else: - # sample etype - etype = rqlst.children[0].solutions[0] - basedescription.append(term.get_type(etype, args)) + if ttype is None or ttype == 'Any': + ttype = None + isfinal = True + else: + isfinal = ttype in BASE_TYPES + if ttype is None or i in unstables: + basedescr.append(None) + todetermine.append( (i, isfinal) ) + else: + basedescr.append(ttype) if not todetermine: - return RepeatList(len(result), tuple(basedescription)) - return self._build_descr(result, basedescription, todetermine) + return RepeatList(len(result), tuple(basedescr)) + return self._build_descr(result, basedescr, todetermine) def _build_descr(self, result, basedescription, todetermine): description = [] etype_from_eid = self.describe for row in result: - row_descr = basedescription + row_descr = basedescription[:] for index, isfinal in todetermine: value = row[index] if value is None: @@ -899,7 +892,8 @@ try: row_descr[index] = etype_from_eid(value)[0] except UnknownEid: - self.critical('wrong eid %s in repository, should check database' % value) + self.critical('wrong eid %s in repository, you should ' + 'db-check the database' % value) row_descr[index] = row[index] = None description.append(tuple(row_descr)) return description diff -r 30b94973bc67 -r 3586d36d2a45 server/sources/rql2sql.py --- a/server/sources/rql2sql.py Wed Jun 09 16:16:54 2010 +0200 +++ b/server/sources/rql2sql.py Thu Jun 10 10:16:59 2010 +0200 @@ -742,29 +742,29 @@ else: # no variables in the RHS sql = self._visit_attribute_relation(relation) + elif (rtype == 'is' and isinstance(rhs.children[0], Constant) + and rhs.children[0].eval(self._args) is None): + # special case "C is NULL" + if lhs.name in self._varmap: + lhssql = self._varmap[lhs.name] + else: + lhssql = lhs.accept(self) + return '%s%s' % (lhssql, rhs.accept(self)) + elif '%s.%s' % (lhs, relation.r_type) in self._varmap: + # relation has already been processed by a previous step + return '' + elif relation.optional: + # check it has not already been treaten (to get necessary + # information to add an outer join condition) + if relation in self._state.done: + return '' + # OPTIONAL relation, generate a left|right outer join + sql = self._visit_outer_join_relation(relation, rschema) + elif rschema.inlined: + sql = self._visit_inlined_relation(relation) else: - if rtype == 'is' and rhs.operator == 'IS': - # special case "C is NULL" - if lhs.name in self._varmap: - lhssql = self._varmap[lhs.name] - else: - lhssql = lhs.accept(self) - return '%s%s' % (lhssql, rhs.accept(self)) - if '%s.%s' % (lhs, relation.r_type) in self._varmap: - # relation has already been processed by a previous step - return - if relation.optional: - # check it has not already been treaten (to get necessary - # information to add an outer join condition) - if relation in self._state.done: - return - # OPTIONAL relation, generate a left|right outer join - sql = self._visit_outer_join_relation(relation, rschema) - elif rschema.inlined: - sql = self._visit_inlined_relation(relation) - else: - # regular (non final) relation - sql = self._visit_relation(relation, rschema) + # regular (non final) relation + sql = self._visit_relation(relation, rschema) return sql def _visit_inlined_relation(self, relation): @@ -1026,7 +1026,7 @@ lhs = None rhs = cmp.children[0] operator = cmp.operator - if operator in ('IS', 'LIKE', 'ILIKE'): + if operator in ('LIKE', 'ILIKE'): if operator == 'ILIKE' and not self.dbhelper.ilike_support: operator = ' LIKE ' else: diff -r 30b94973bc67 -r 3586d36d2a45 server/test/unittest_querier.py --- a/server/test/unittest_querier.py Wed Jun 09 16:16:54 2010 +0200 +++ b/server/test/unittest_querier.py Thu Jun 10 10:16:59 2010 +0200 @@ -789,6 +789,15 @@ 'end', 'finie', 'markasdone', 'pitetre', 'redoit', 'start', 'todo']) + def test_select_union_description_diff_var(self): + eid1 = self.execute('CWGroup X WHERE X name "managers"')[0][0] + eid2 = self.execute('CWUser X WHERE X login "admin"')[0][0] + rset = self.execute('(Any X WHERE X eid %(x)s)' + ' UNION ' + '(Any Y WHERE Y eid %(y)s)', + {'x': eid1, 'y': eid2}) + self.assertEquals(rset.description[:], [('CWGroup',), ('CWUser',)]) + def test_exists(self): geid = self.execute("INSERT CWGroup X: X name 'lulufanclub'")[0][0] self.execute("SET U in_group G WHERE G name 'lulufanclub'")