cubicweb/rset.py
changeset 11870 3a84a79c4ed5
parent 11868 d5181d7f1389
child 11874 ea1d92b677b5
equal deleted inserted replaced
11869:d8b66e3fd335 11870:3a84a79c4ed5
     1 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
     1 # copyright 2003-2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
     2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
     2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
     3 #
     3 #
     4 # This file is part of CubicWeb.
     4 # This file is part of CubicWeb.
     5 #
     5 #
     6 # CubicWeb is free software: you can redistribute it and/or modify it under the
     6 # CubicWeb is free software: you can redistribute it and/or modify it under the
    92         else:
    92         else:
    93             pattern = '<resultset %r (%s rows): %s>'
    93             pattern = '<resultset %r (%s rows): %s>'
    94 
    94 
    95         if not self.description:
    95         if not self.description:
    96             return pattern % (self.rql, len(self.rows),
    96             return pattern % (self.rql, len(self.rows),
    97                                                      '\n'.join(str(r) for r in rows))
    97                               '\n'.join(str(r) for r in rows))
    98         return pattern % (self.rql, len(self.rows),
    98         return pattern % (self.rql, len(self.rows),
    99                                                  '\n'.join('%s (%s)' % (r, d)
    99                           '\n'.join('%s (%s)' % (r, d)
   100                                                            for r, d in zip(rows, self.description)))
   100                                     for r, d in zip(rows, self.description)))
   101 
   101 
   102     def possible_actions(self, **kwargs):
   102     def possible_actions(self, **kwargs):
   103         if self._rsetactions is None:
   103         if self._rsetactions is None:
   104             self._rsetactions = {}
   104             self._rsetactions = {}
   105         if kwargs:
   105         if kwargs:
   118         """returns the result set's size"""
   118         """returns the result set's size"""
   119         return self.rowcount
   119         return self.rowcount
   120 
   120 
   121     def __getitem__(self, i):
   121     def __getitem__(self, i):
   122         """returns the ith element of the result set"""
   122         """returns the ith element of the result set"""
   123         return self.rows[i] #ResultSetRow(self.rows[i])
   123         return self.rows[i]
   124 
   124 
   125     def __iter__(self):
   125     def __iter__(self):
   126         """Returns an iterator over rows"""
   126         """Returns an iterator over rows"""
   127         return iter(self.rows)
   127         return iter(self.rows)
   128 
   128 
   130         # XXX buggy implementation (.rql and .args attributes at least much
   130         # XXX buggy implementation (.rql and .args attributes at least much
   131         # probably differ)
   131         # probably differ)
   132         # at least rql could be fixed now that we have union and sub-queries
   132         # at least rql could be fixed now that we have union and sub-queries
   133         # but I tend to think that since we have that, we should not need this
   133         # but I tend to think that since we have that, we should not need this
   134         # method anymore (syt)
   134         # method anymore (syt)
   135         rset = ResultSet(self.rows+rset.rows, self.rql, self.args,
   135         rset = ResultSet(self.rows + rset.rows, self.rql, self.args,
   136                          self.description + rset.description)
   136                          self.description + rset.description)
   137         rset.req = self.req
   137         rset.req = self.req
   138         return rset
   138         return rset
   139 
   139 
   140     def copy(self, rows=None, descr=None):
   140     def copy(self, rows=None, descr=None):
   161         """
   161         """
   162         rows, descr = [], []
   162         rows, descr = [], []
   163         rset = self.copy(rows, descr)
   163         rset = self.copy(rows, descr)
   164         for row, desc in zip(self.rows, self.description):
   164         for row, desc in zip(self.rows, self.description):
   165             nrow, ndesc = transformcb(row, desc)
   165             nrow, ndesc = transformcb(row, desc)
   166             if ndesc: # transformcb returns None for ndesc to skip that row
   166             if ndesc:  # transformcb returns None for ndesc to skip that row
   167                 rows.append(nrow)
   167                 rows.append(nrow)
   168                 descr.append(ndesc)
   168                 descr.append(ndesc)
   169         rset.rowcount = len(rows)
   169         rset.rowcount = len(rows)
   170         return rset
   170         return rset
   171 
   171 
   189                 continue
   189                 continue
   190             rows.append(self.rows[i])
   190             rows.append(self.rows[i])
   191             descr.append(self.description[i])
   191             descr.append(self.description[i])
   192         rset.rowcount = len(rows)
   192         rset.rowcount = len(rows)
   193         return rset
   193         return rset
   194 
       
   195 
   194 
   196     def sorted_rset(self, keyfunc, reverse=False, col=0):
   195     def sorted_rset(self, keyfunc, reverse=False, col=0):
   197         """sorts the result set according to a given keyfunc
   196         """sorts the result set according to a given keyfunc
   198 
   197 
   199         :type keyfunc: callable(entity)
   198         :type keyfunc: callable(entity)
   306             select.limit, select.offset = olimit, ooffset
   305             select.limit, select.offset = olimit, ooffset
   307         else:
   306         else:
   308             newselect = stmts.Select()
   307             newselect = stmts.Select()
   309             newselect.limit = limit
   308             newselect.limit = limit
   310             newselect.offset = offset
   309             newselect.offset = offset
   311             aliases = [nodes.VariableRef(newselect.get_variable(chr(65+i), i))
   310             aliases = [nodes.VariableRef(newselect.get_variable(chr(65 + i), i))
   312                        for i in range(len(rqlst.children[0].selection))]
   311                        for i in range(len(rqlst.children[0].selection))]
   313             for vref in aliases:
   312             for vref in aliases:
   314                 newselect.append_selected(nodes.VariableRef(vref.variable))
   313                 newselect.append_selected(nodes.VariableRef(vref.variable))
   315             newselect.set_with([nodes.SubQuery(aliases, rqlst)], check=False)
   314             newselect.set_with([nodes.SubQuery(aliases, rqlst)], check=False)
   316             newunion = stmts.Union()
   315             newunion = stmts.Union()
   334           if true, the result set is modified in place, else a new result set
   333           if true, the result set is modified in place, else a new result set
   335           is returned and the original is left unmodified
   334           is returned and the original is left unmodified
   336 
   335 
   337         :rtype: `ResultSet`
   336         :rtype: `ResultSet`
   338         """
   337         """
   339         stop = limit+offset
   338         stop = limit + offset
   340         rows = self.rows[offset:stop]
   339         rows = self.rows[offset:stop]
   341         descr = self.description[offset:stop]
   340         descr = self.description[offset:stop]
   342         if inplace:
   341         if inplace:
   343             rset = self
   342             rset = self
   344             rset.rows, rset.description = rows, descr
   343             rset.rows, rset.description = rows, descr
   590         last = None
   589         last = None
   591         for i, row in enumerate(self.description):
   590         for i, row in enumerate(self.description):
   592             if row != last:
   591             if row != last:
   593                 if last is not None:
   592                 if last is not None:
   594                     result[-1][1] = i - 1
   593                     result[-1][1] = i - 1
   595                 result.append( [i, None, row] )
   594                 result.append([i, None, row])
   596                 last = row
   595                 last = row
   597         if last is not None:
   596         if last is not None:
   598             result[-1][1] = i
   597             result[-1][1] = i
   599         return result
   598         return result
   600 
   599 
   663             index = rel.children[0].root_selection_index()
   662             index = rel.children[0].root_selection_index()
   664             if index is not None and self.rows[row][index]:
   663             if index is not None and self.rows[row][index]:
   665                 try:
   664                 try:
   666                     entity = self.get_entity(row, index)
   665                     entity = self.get_entity(row, index)
   667                     return entity, rel.r_type
   666                     return entity, rel.r_type
   668                 except NotAnEntity as exc:
   667                 except NotAnEntity:
   669                     return None, None
   668                     return None, None
   670         return None, None
   669         return None, None
   671 
   670 
   672     @cached
   671     @cached
   673     def searched_text(self):
   672     def searched_text(self):
   681             if rel.r_type == 'has_text':
   680             if rel.r_type == 'has_text':
   682                 __, rhs = rel.get_variable_parts()
   681                 __, rhs = rel.get_variable_parts()
   683                 return rhs.eval(self.args)
   682                 return rhs.eval(self.args)
   684         return None
   683         return None
   685 
   684 
       
   685 
   686 def _get_variable(term):
   686 def _get_variable(term):
   687     # XXX rewritten const
   687     # XXX rewritten const
   688     # use iget_nodes for (hack) case where we have things like MAX(V)
   688     # use iget_nodes for (hack) case where we have things like MAX(V)
   689     for vref in term.iget_nodes(nodes.VariableRef):
   689     for vref in term.iget_nodes(nodes.VariableRef):
   690         return vref.variable
   690         return vref.variable
       
   691 
   691 
   692 
   692 def attr_desc_iterator(select, selectidx, rootidx):
   693 def attr_desc_iterator(select, selectidx, rootidx):
   693     """return an iterator on a list of 2-uple (index, attr_relation)
   694     """return an iterator on a list of 2-uple (index, attr_relation)
   694     localizing attribute relations of the main variable in a result's row
   695     localizing attribute relations of the main variable in a result's row
   695 
   696