13 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
13 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
14 # details. |
14 # details. |
15 # |
15 # |
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 """Repository users' and internal' sessions. |
18 """Repository users' and internal' sessions.""" |
19 |
19 |
20 """ |
|
21 from __future__ import with_statement |
20 from __future__ import with_statement |
22 |
21 |
23 __docformat__ = "restructuredtext en" |
22 __docformat__ = "restructuredtext en" |
24 |
23 |
25 import sys |
24 import sys |
27 from time import time |
26 from time import time |
28 from uuid import uuid4 |
27 from uuid import uuid4 |
29 from warnings import warn |
28 from warnings import warn |
30 |
29 |
31 from logilab.common.deprecation import deprecated |
30 from logilab.common.deprecation import deprecated |
32 from rql.nodes import VariableRef, Function, ETYPE_PYOBJ_MAP, etype_from_pyobj |
31 from rql.nodes import ETYPE_PYOBJ_MAP, etype_from_pyobj |
33 from yams import BASE_TYPES |
32 from yams import BASE_TYPES |
34 |
33 |
35 from cubicweb import Binary, UnknownEid, schema |
34 from cubicweb import Binary, UnknownEid, schema |
36 from cubicweb.req import RequestSessionBase |
35 from cubicweb.req import RequestSessionBase |
37 from cubicweb.dbapi import ConnectionProperties |
36 from cubicweb.dbapi import ConnectionProperties |
46 # dataimport.NoHookRQLObjectStore, and we don't want to record them |
45 # dataimport.NoHookRQLObjectStore, and we don't want to record them |
47 # anyway in the later case |
46 # anyway in the later case |
48 NO_UNDO_TYPES.add('is') |
47 NO_UNDO_TYPES.add('is') |
49 NO_UNDO_TYPES.add('is_instance_of') |
48 NO_UNDO_TYPES.add('is_instance_of') |
50 # XXX rememberme,forgotpwd,apycot,vcsfile |
49 # XXX rememberme,forgotpwd,apycot,vcsfile |
51 |
|
52 def is_final(rqlst, variable, args): |
|
53 # try to find if this is a final var or not |
|
54 for select in rqlst.children: |
|
55 for sol in select.solutions: |
|
56 etype = variable.get_type(sol, args) |
|
57 if etype is None: |
|
58 continue |
|
59 if etype in BASE_TYPES: |
|
60 return True |
|
61 return False |
|
62 |
50 |
63 def _make_description(selected, args, solution): |
51 def _make_description(selected, args, solution): |
64 """return a description for a result set""" |
52 """return a description for a result set""" |
65 description = [] |
53 description = [] |
66 for term in selected: |
54 for term in selected: |
868 |
856 |
869 XXX could probably be done more efficiently during execution of query |
857 XXX could probably be done more efficiently during execution of query |
870 """ |
858 """ |
871 # not so easy, looks for variable which changes from one solution |
859 # not so easy, looks for variable which changes from one solution |
872 # to another |
860 # to another |
873 unstables = rqlst.get_variable_variables() |
861 unstables = rqlst.get_variable_indices() |
874 basedescription = [] |
862 basedescr = [] |
875 todetermine = [] |
863 todetermine = [] |
876 selected = rqlst.children[0].selection # sample selection |
864 sampleselect = rqlst.children[0] |
877 for i, term in enumerate(selected): |
865 samplesols = sampleselect.solutions[0] |
878 if isinstance(term, Function) and term.descr().rtype is not None: |
866 for i, term in enumerate(sampleselect.selection): |
879 basedescription.append(term.get_type(term.descr().rtype, args)) |
867 try: |
880 continue |
868 ttype = term.get_type(samplesols, args) |
881 for vref in term.get_nodes(VariableRef): |
869 except CoercionError: |
882 if vref.name in unstables: |
870 ttype = None |
883 basedescription.append(None) |
871 isfinal = True |
884 todetermine.append( (i, is_final(rqlst, vref.variable, args)) ) |
|
885 break |
|
886 else: |
872 else: |
887 # sample etype |
873 if ttype is None or ttype == 'Any': |
888 etype = rqlst.children[0].solutions[0] |
874 ttype = None |
889 basedescription.append(term.get_type(etype, args)) |
875 isfinal = True |
|
876 else: |
|
877 isfinal = ttype in BASE_TYPES |
|
878 if ttype is None or i in unstables: |
|
879 basedescr.append(None) |
|
880 todetermine.append( (i, isfinal) ) |
|
881 else: |
|
882 basedescr.append(ttype) |
890 if not todetermine: |
883 if not todetermine: |
891 return RepeatList(len(result), tuple(basedescription)) |
884 return RepeatList(len(result), tuple(basedescr)) |
892 return self._build_descr(result, basedescription, todetermine) |
885 return self._build_descr(result, basedescr, todetermine) |
893 |
886 |
894 def _build_descr(self, result, basedescription, todetermine): |
887 def _build_descr(self, result, basedescription, todetermine): |
895 description = [] |
888 description = [] |
896 etype_from_eid = self.describe |
889 etype_from_eid = self.describe |
897 for row in result: |
890 for row in result: |
898 row_descr = basedescription |
891 row_descr = basedescription[:] |
899 for index, isfinal in todetermine: |
892 for index, isfinal in todetermine: |
900 value = row[index] |
893 value = row[index] |
901 if value is None: |
894 if value is None: |
902 # None value inserted by an outer join, no type |
895 # None value inserted by an outer join, no type |
903 row_descr[index] = None |
896 row_descr[index] = None |
906 row_descr[index] = etype_from_pyobj(value) |
899 row_descr[index] = etype_from_pyobj(value) |
907 else: |
900 else: |
908 try: |
901 try: |
909 row_descr[index] = etype_from_eid(value)[0] |
902 row_descr[index] = etype_from_eid(value)[0] |
910 except UnknownEid: |
903 except UnknownEid: |
911 self.critical('wrong eid %s in repository, should check database' % value) |
904 self.critical('wrong eid %s in repository, you should ' |
|
905 'db-check the database' % value) |
912 row_descr[index] = row[index] = None |
906 row_descr[index] = row[index] = None |
913 description.append(tuple(row_descr)) |
907 description.append(tuple(row_descr)) |
914 return description |
908 return description |
915 |
909 |
916 # deprecated ############################################################### |
910 # deprecated ############################################################### |