rset.py
author Rémi Cardona <remi.cardona@logilab.fr>
Tue, 23 Jun 2015 10:02:41 +0200
changeset 10435 5b33ca2c61e0
parent 10354 635cfac73d28
child 10593 03ce3d24db87
permissions -rw-r--r--
[server/session] Roll back in connection exit This was changed in commit 8b35a898b334 "[server] remove cnxset tracking, it is now unneeded". When exiting a CubicWeb Connection, the database connection is put back into the common pool. At that point anything done during the lifetime of the CubicWeb Connection needs to be committed or rolled back. Do a proper rollback to finish the transaction, as was happening before the above-mentionned commit. This showed up on testing with postgresql, when a DB schema modification was blocked by an old connection that was still "in transaction".
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
7395
09ffcc04bd21 [rset] close #1683703: rset.get_entity crash on rql query with subquery and aggregat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6915
diff changeset
     1
# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
5421
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5314
diff changeset
     2
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5314
diff changeset
     3
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5314
diff changeset
     4
# This file is part of CubicWeb.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5314
diff changeset
     5
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5314
diff changeset
     6
# CubicWeb is free software: you can redistribute it and/or modify it under the
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5314
diff changeset
     7
# terms of the GNU Lesser General Public License as published by the Free
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5314
diff changeset
     8
# Software Foundation, either version 2.1 of the License, or (at your option)
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5314
diff changeset
     9
# any later version.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5314
diff changeset
    10
#
5424
8ecbcbff9777 replace logilab-common by CubicWeb in disclaimer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5421
diff changeset
    11
# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
5421
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5314
diff changeset
    12
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5314
diff changeset
    13
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5314
diff changeset
    14
# details.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5314
diff changeset
    15
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5314
diff changeset
    16
# You should have received a copy of the GNU Lesser General Public License along
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5314
diff changeset
    17
# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
5671
3a2063b752f3 [editform] consistent [do]reledit between attributes and relations: check if rdef is hidden in main section of uicfg.afs for both attributes and relations, and in the reledit view, not in doreledit
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5667
diff changeset
    18
"""The `ResultSet` class which is returned as result of an rql query"""
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    19
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    20
__docformat__ = "restructuredtext en"
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    21
10087
ed0b076c119b [rset] kill the rset._rqlst cache
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9820
diff changeset
    22
from warnings import warn
ed0b076c119b [rset] kill the rset._rqlst cache
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9820
diff changeset
    23
10313
ae9e23cf8790 [rset] Deprecate the 'encoded' argument to ResultSet.printable_rql()
Rémi Cardona <remi.cardona@free.fr>
parents: 10187
diff changeset
    24
from logilab.common import nullobject
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    25
from logilab.common.decorators import cached, clear_cache, copy_cache
2792
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
    26
from rql import nodes, stmts
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    27
9347
bd841d6ae723 [rset] New method: ResultSet.one()
Christophe de Vienne <cdevienne@gmail.com>
parents: 9331
diff changeset
    28
from cubicweb import NotAnEntity, NoResultError, MultipleResultsError
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1477
diff changeset
    29
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    30
10313
ae9e23cf8790 [rset] Deprecate the 'encoded' argument to ResultSet.printable_rql()
Rémi Cardona <remi.cardona@free.fr>
parents: 10187
diff changeset
    31
_MARKER = nullobject()
ae9e23cf8790 [rset] Deprecate the 'encoded' argument to ResultSet.printable_rql()
Rémi Cardona <remi.cardona@free.fr>
parents: 10187
diff changeset
    32
ae9e23cf8790 [rset] Deprecate the 'encoded' argument to ResultSet.printable_rql()
Rémi Cardona <remi.cardona@free.fr>
parents: 10187
diff changeset
    33
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    34
class ResultSet(object):
5312
d2dbba898a96 [doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5311
diff changeset
    35
    """A result set wraps a RQL query result. This object implements
d2dbba898a96 [doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5311
diff changeset
    36
    partially the list protocol to allow direct use as a list of
d2dbba898a96 [doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5311
diff changeset
    37
    result rows.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    38
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    39
    :type rowcount: int
5312
d2dbba898a96 [doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5311
diff changeset
    40
    :param rowcount: number of rows in the result
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    41
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    42
    :type rows: list
5312
d2dbba898a96 [doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5311
diff changeset
    43
    :param rows: list of rows of result
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    44
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    45
    :type description: list
5312
d2dbba898a96 [doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5311
diff changeset
    46
    :param description:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    47
      result's description, using the same structure as the result itself
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    48
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    49
    :type rql: str or unicode
5312
d2dbba898a96 [doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5311
diff changeset
    50
    :param rql: the original RQL query string
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    51
    """
5740
46207f491a51 [rset] make rsets picklable (again ?) #1056422
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5671
diff changeset
    52
9281
49a7392bb5b5 [rset] make sure rset.description is always a list
Julien Cristau <julien.cristau@logilab.fr>
parents: 8695
diff changeset
    53
    def __init__(self, results, rql, args=None, description=None, rqlst=None):
10087
ed0b076c119b [rset] kill the rset._rqlst cache
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9820
diff changeset
    54
        if rqlst is not None:
ed0b076c119b [rset] kill the rset._rqlst cache
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9820
diff changeset
    55
            warn('[3.20] rqlst parameter is deprecated',
ed0b076c119b [rset] kill the rset._rqlst cache
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9820
diff changeset
    56
                 DeprecationWarning, stacklevel=2)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    57
        self.rows = results
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    58
        self.rowcount = results and len(results) or 0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    59
        # original query and arguments
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    60
        self.rql = rql
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    61
        self.args = args
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    62
        # entity types for each cell (same shape as rows)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    63
        # maybe discarded if specified when the query has been executed
9331
c6f54ed6b60a [rset] Fix regression with rset copying (closes #3344410)
Julien Cristau <julien.cristau@logilab.fr>
parents: 9281
diff changeset
    64
        if description is None:
c6f54ed6b60a [rset] Fix regression with rset copying (closes #3344410)
Julien Cristau <julien.cristau@logilab.fr>
parents: 9281
diff changeset
    65
            self.description = []
c6f54ed6b60a [rset] Fix regression with rset copying (closes #3344410)
Julien Cristau <julien.cristau@logilab.fr>
parents: 9281
diff changeset
    66
        else:
c6f54ed6b60a [rset] Fix regression with rset copying (closes #3344410)
Julien Cristau <julien.cristau@logilab.fr>
parents: 9281
diff changeset
    67
            self.description = description
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    68
        # set to (limit, offset) when a result set is limited using the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    69
        # .limit method
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    70
        self.limited = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    71
        # set by the cursor which returned this resultset
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    72
        self.req = None
1381
6042f1b342bb consider kwargs in possible_actions
sylvain.thenault@logilab.fr
parents: 616
diff changeset
    73
        # actions cache
6042f1b342bb consider kwargs in possible_actions
sylvain.thenault@logilab.fr
parents: 616
diff changeset
    74
        self._rsetactions = None
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1477
diff changeset
    75
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    76
    def __str__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    77
        if not self.rows:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    78
            return '<empty resultset %s>' % self.rql
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    79
        return '<resultset %s (%s rows)>' % (self.rql, len(self.rows))
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1477
diff changeset
    80
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    81
    def __repr__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    82
        if not self.rows:
170
455ff18ef28e use repr (instead of str) to print rql in __repr__ method of a result set
Stephanie Marcu <stephanie.marcu@logilab.fr>
parents: 0
diff changeset
    83
            return '<empty resultset for %r>' % self.rql
616
545a7e18c47f don't display too much rset rows
sylvain.thenault@logilab.fr
parents: 572
diff changeset
    84
        rows = self.rows
545a7e18c47f don't display too much rset rows
sylvain.thenault@logilab.fr
parents: 572
diff changeset
    85
        if len(rows) > 10:
545a7e18c47f don't display too much rset rows
sylvain.thenault@logilab.fr
parents: 572
diff changeset
    86
            rows = rows[:10] + ['...']
5687
3ea39709b50e [rset] Add a line break the first result in repr of multiple rows rset
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 5679
diff changeset
    87
        if len(rows) > 1:
3ea39709b50e [rset] Add a line break the first result in repr of multiple rows rset
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 5679
diff changeset
    88
            # add a line break before first entity if more that one.
7395
09ffcc04bd21 [rset] close #1683703: rset.get_entity crash on rql query with subquery and aggregat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6915
diff changeset
    89
            pattern = '<resultset %r (%s rows):\n%s>'
5687
3ea39709b50e [rset] Add a line break the first result in repr of multiple rows rset
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 5679
diff changeset
    90
        else:
3ea39709b50e [rset] Add a line break the first result in repr of multiple rows rset
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 5679
diff changeset
    91
            pattern = '<resultset %r (%s rows): %s>'
3ea39709b50e [rset] Add a line break the first result in repr of multiple rows rset
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 5679
diff changeset
    92
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    93
        if not self.description:
5687
3ea39709b50e [rset] Add a line break the first result in repr of multiple rows rset
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 5679
diff changeset
    94
            return pattern % (self.rql, len(self.rows),
616
545a7e18c47f don't display too much rset rows
sylvain.thenault@logilab.fr
parents: 572
diff changeset
    95
                                                     '\n'.join(str(r) for r in rows))
5687
3ea39709b50e [rset] Add a line break the first result in repr of multiple rows rset
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 5679
diff changeset
    96
        return pattern % (self.rql, len(self.rows),
616
545a7e18c47f don't display too much rset rows
sylvain.thenault@logilab.fr
parents: 572
diff changeset
    97
                                                 '\n'.join('%s (%s)' % (r, d)
545a7e18c47f don't display too much rset rows
sylvain.thenault@logilab.fr
parents: 572
diff changeset
    98
                                                           for r, d in zip(rows, self.description)))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    99
1381
6042f1b342bb consider kwargs in possible_actions
sylvain.thenault@logilab.fr
parents: 616
diff changeset
   100
    def possible_actions(self, **kwargs):
6042f1b342bb consider kwargs in possible_actions
sylvain.thenault@logilab.fr
parents: 616
diff changeset
   101
        if self._rsetactions is None:
6042f1b342bb consider kwargs in possible_actions
sylvain.thenault@logilab.fr
parents: 616
diff changeset
   102
            self._rsetactions = {}
6042f1b342bb consider kwargs in possible_actions
sylvain.thenault@logilab.fr
parents: 616
diff changeset
   103
        if kwargs:
6042f1b342bb consider kwargs in possible_actions
sylvain.thenault@logilab.fr
parents: 616
diff changeset
   104
            key = tuple(sorted(kwargs.iteritems()))
6042f1b342bb consider kwargs in possible_actions
sylvain.thenault@logilab.fr
parents: 616
diff changeset
   105
        else:
6042f1b342bb consider kwargs in possible_actions
sylvain.thenault@logilab.fr
parents: 616
diff changeset
   106
            key = None
6042f1b342bb consider kwargs in possible_actions
sylvain.thenault@logilab.fr
parents: 616
diff changeset
   107
        try:
6042f1b342bb consider kwargs in possible_actions
sylvain.thenault@logilab.fr
parents: 616
diff changeset
   108
            return self._rsetactions[key]
6042f1b342bb consider kwargs in possible_actions
sylvain.thenault@logilab.fr
parents: 616
diff changeset
   109
        except KeyError:
4850
bd640b137f50 [refactor] drop rset.vreg attribute, vreg should be accessed through rset.req. Also kill decorate_rset, simply set rset.req where we were calling this method.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4475
diff changeset
   110
            actions = self.req.vreg['actions'].poss_visible_objects(
2650
18aec79ec3a3 R [vreg] important refactoring of the vregistry, moving behaviour to end dictionnary (and so leaving room for more flexibility ; keep bw compat ; update api usage in cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2648
diff changeset
   111
                self.req, rset=self, **kwargs)
1381
6042f1b342bb consider kwargs in possible_actions
sylvain.thenault@logilab.fr
parents: 616
diff changeset
   112
            self._rsetactions[key] = actions
6042f1b342bb consider kwargs in possible_actions
sylvain.thenault@logilab.fr
parents: 616
diff changeset
   113
            return actions
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1477
diff changeset
   114
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   115
    def __len__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   116
        """returns the result set's size"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   117
        return self.rowcount
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   118
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   119
    def __getitem__(self, i):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   120
        """returns the ith element of the result set"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   121
        return self.rows[i] #ResultSetRow(self.rows[i])
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1477
diff changeset
   122
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   123
    def __getslice__(self, i, j):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   124
        """returns slice [i:j] of the result set"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   125
        return self.rows[i:j]
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1477
diff changeset
   126
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   127
    def __iter__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   128
        """Returns an iterator over rows"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   129
        return iter(self.rows)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   130
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   131
    def __add__(self, rset):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   132
        # XXX buggy implementation (.rql and .args attributes at least much
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   133
        # probably differ)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   134
        # at least rql could be fixed now that we have union and sub-queries
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   135
        # but I tend to think that since we have that, we should not need this
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   136
        # method anymore (syt)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   137
        rset = ResultSet(self.rows+rset.rows, self.rql, self.args,
5072
072ae171aeb0 [cleanup] style fixes, add nodes, 0.2 cents refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4951
diff changeset
   138
                         self.description + rset.description)
4850
bd640b137f50 [refactor] drop rset.vreg attribute, vreg should be accessed through rset.req. Also kill decorate_rset, simply set rset.req where we were calling this method.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4475
diff changeset
   139
        rset.req = self.req
bd640b137f50 [refactor] drop rset.vreg attribute, vreg should be accessed through rset.req. Also kill decorate_rset, simply set rset.req where we were calling this method.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4475
diff changeset
   140
        return rset
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   141
3764
034aa14b740a drop _prepare_copy method from rset in favor of a more generic copy method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   142
    def copy(self, rows=None, descr=None):
034aa14b740a drop _prepare_copy method from rset in favor of a more generic copy method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   143
        if rows is None:
034aa14b740a drop _prepare_copy method from rset in favor of a more generic copy method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   144
            rows = self.rows[:]
034aa14b740a drop _prepare_copy method from rset in favor of a more generic copy method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   145
            descr = self.description[:]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   146
        rset = ResultSet(rows, self.rql, self.args, descr)
4850
bd640b137f50 [refactor] drop rset.vreg attribute, vreg should be accessed through rset.req. Also kill decorate_rset, simply set rset.req where we were calling this method.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4475
diff changeset
   147
        rset.req = self.req
bd640b137f50 [refactor] drop rset.vreg attribute, vreg should be accessed through rset.req. Also kill decorate_rset, simply set rset.req where we were calling this method.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4475
diff changeset
   148
        return rset
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   149
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   150
    def transformed_rset(self, transformcb):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   151
        """ the result set according to a given column types
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   152
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   153
        :type transormcb: callable(row, desc)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   154
        :param transformcb:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   155
          a callable which should take a row and its type description as
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   156
          parameters, and return the transformed row and type description.
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1477
diff changeset
   157
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   158
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   159
        :type col: int
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   160
        :param col: the column index
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   161
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   162
        :rtype: `ResultSet`
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   163
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   164
        rows, descr = [], []
3764
034aa14b740a drop _prepare_copy method from rset in favor of a more generic copy method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   165
        rset = self.copy(rows, descr)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   166
        for row, desc in zip(self.rows, self.description):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   167
            nrow, ndesc = transformcb(row, desc)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   168
            if ndesc: # transformcb returns None for ndesc to skip that row
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   169
                rows.append(nrow)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   170
                descr.append(ndesc)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   171
        rset.rowcount = len(rows)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   172
        return rset
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   173
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   174
    def filtered_rset(self, filtercb, col=0):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   175
        """filter the result set according to a given filtercb
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   176
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   177
        :type filtercb: callable(entity)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   178
        :param filtercb:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   179
          a callable which should take an entity as argument and return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   180
          False if it should be skipped, else True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   181
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   182
        :type col: int
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   183
        :param col: the column index
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   184
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   185
        :rtype: `ResultSet`
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   186
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   187
        rows, descr = [], []
3764
034aa14b740a drop _prepare_copy method from rset in favor of a more generic copy method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   188
        rset = self.copy(rows, descr)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   189
        for i in xrange(len(self)):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   190
            if not filtercb(self.get_entity(i, col)):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   191
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   192
            rows.append(self.rows[i])
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   193
            descr.append(self.description[i])
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   194
        rset.rowcount = len(rows)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   195
        return rset
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   196
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   197
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   198
    def sorted_rset(self, keyfunc, reverse=False, col=0):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   199
        """sorts the result set according to a given keyfunc
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   200
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   201
        :type keyfunc: callable(entity)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   202
        :param keyfunc:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   203
          a callable which should take an entity as argument and return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   204
          the value used to compare and sort
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   205
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   206
        :type reverse: bool
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   207
        :param reverse: if the result should be reversed
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   208
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   209
        :type col: int
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   210
        :param col: the column index. if col = -1, the whole row are used
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   211
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   212
        :rtype: `ResultSet`
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   213
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   214
        rows, descr = [], []
3764
034aa14b740a drop _prepare_copy method from rset in favor of a more generic copy method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   215
        rset = self.copy(rows, descr)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   216
        if col >= 0:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   217
            entities = sorted(enumerate(self.entities(col)),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   218
                              key=lambda (i, e): keyfunc(e), reverse=reverse)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   219
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   220
            entities = sorted(enumerate(self),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   221
                              key=lambda (i, e): keyfunc(e), reverse=reverse)
1132
96752791c2b6 pylint cleanup
sylvain.thenault@logilab.fr
parents: 616
diff changeset
   222
        for index, _ in entities:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   223
            rows.append(self.rows[index])
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   224
            descr.append(self.description[index])
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   225
        rset.rowcount = len(rows)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   226
        return rset
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   227
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   228
    def split_rset(self, keyfunc=None, col=0, return_dict=False):
5312
d2dbba898a96 [doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5311
diff changeset
   229
        """splits the result set in multiple result sets according to
d2dbba898a96 [doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5311
diff changeset
   230
        a given key
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1477
diff changeset
   231
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   232
        :type keyfunc: callable(entity or FinalType)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   233
        :param keyfunc:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   234
          a callable which should take a value of the rset in argument and
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   235
          return the value used to group the value. If not define, raw value
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   236
          of the specified columns is used.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   237
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   238
        :type col: int
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   239
        :param col: the column index. if col = -1, the whole row are used
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   240
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   241
        :type return_dict: Boolean
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   242
        :param return_dict: If true, the function return a mapping
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   243
            (key -> rset) instead of a list of rset
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   244
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   245
        :rtype: List of `ResultSet` or mapping of  `ResultSet`
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   246
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   247
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   248
        result = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   249
        mapping = {}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   250
        for idx, line in enumerate(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   251
            if col >= 0:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   252
                try:
1132
96752791c2b6 pylint cleanup
sylvain.thenault@logilab.fr
parents: 616
diff changeset
   253
                    key = self.get_entity(idx, col)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   254
                except NotAnEntity:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   255
                    key = line[col]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   256
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   257
                key = line
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   258
            if keyfunc is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   259
                key = keyfunc(key)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   260
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   261
            if key not in mapping:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   262
                rows, descr = [], []
3764
034aa14b740a drop _prepare_copy method from rset in favor of a more generic copy method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   263
                rset = self.copy(rows, descr)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   264
                mapping[key] = rset
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   265
                result.append(rset)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   266
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   267
                rset = mapping[key]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   268
            rset.rows.append(self.rows[idx])
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   269
            rset.description.append(self.description[idx])
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   270
        for rset in result:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   271
            rset.rowcount = len(rset.rows)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   272
        if return_dict:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   273
            return mapping
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   274
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   275
            return result
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   276
2792
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   277
    def limited_rql(self):
5312
d2dbba898a96 [doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5311
diff changeset
   278
        """returns a printable rql for the result set associated to the object,
2792
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   279
        with limit/offset correctly set according to maximum page size and
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   280
        currently displayed page when necessary
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   281
        """
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   282
        # try to get page boundaries from the navigation component
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   283
        # XXX we should probably not have a ref to this component here (eg in
4023
eae23c40627a drop common subpackage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3998
diff changeset
   284
        #     cubicweb)
4850
bd640b137f50 [refactor] drop rset.vreg attribute, vreg should be accessed through rset.req. Also kill decorate_rset, simply set rset.req where we were calling this method.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4475
diff changeset
   285
        nav = self.req.vreg['components'].select_or_none('navigation', self.req,
bd640b137f50 [refactor] drop rset.vreg attribute, vreg should be accessed through rset.req. Also kill decorate_rset, simply set rset.req where we were calling this method.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4475
diff changeset
   286
                                                         rset=self)
2792
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   287
        if nav:
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   288
            start, stop = nav.page_boundaries()
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   289
            rql = self._limit_offset_rql(stop - start, start)
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   290
        # result set may have be limited manually in which case navigation won't
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   291
        # apply
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   292
        elif self.limited:
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   293
            rql = self._limit_offset_rql(*self.limited)
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   294
        # navigation component doesn't apply and rset has not been limited, no
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   295
        # need to limit query
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   296
        else:
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   297
            rql = self.printable_rql()
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   298
        return rql
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   299
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   300
    def _limit_offset_rql(self, limit, offset):
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   301
        rqlst = self.syntax_tree()
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   302
        if len(rqlst.children) == 1:
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   303
            select = rqlst.children[0]
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   304
            olimit, ooffset = select.limit, select.offset
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   305
            select.limit, select.offset = limit, offset
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   306
            rql = rqlst.as_string(kwargs=self.args)
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   307
            # restore original limit/offset
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   308
            select.limit, select.offset = olimit, ooffset
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   309
        else:
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   310
            newselect = stmts.Select()
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   311
            newselect.limit = limit
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   312
            newselect.offset = offset
4939
349af486f5ed fix limited_rql w/ UNION query
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4475
diff changeset
   313
            aliases = [nodes.VariableRef(newselect.get_variable(chr(65+i), i))
349af486f5ed fix limited_rql w/ UNION query
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4475
diff changeset
   314
                       for i in xrange(len(rqlst.children[0].selection))]
349af486f5ed fix limited_rql w/ UNION query
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4475
diff changeset
   315
            for vref in aliases:
349af486f5ed fix limited_rql w/ UNION query
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4475
diff changeset
   316
                newselect.append_selected(nodes.VariableRef(vref.variable))
2792
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   317
            newselect.set_with([nodes.SubQuery(aliases, rqlst)], check=False)
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   318
            newunion = stmts.Union()
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   319
            newunion.append(newselect)
4939
349af486f5ed fix limited_rql w/ UNION query
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4475
diff changeset
   320
            rql = newunion.as_string(kwargs=self.args)
2792
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   321
            rqlst.parent = None
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   322
        return rql
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   323
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   324
    def limit(self, limit, offset=0, inplace=False):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   325
        """limit the result set to the given number of rows optionaly starting
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   326
        from an index different than 0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   327
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   328
        :type limit: int
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   329
        :param limit: the maximum number of results
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   330
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   331
        :type offset: int
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   332
        :param offset: the offset index
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1477
diff changeset
   333
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   334
        :type inplace: bool
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   335
        :param inplace:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   336
          if true, the result set is modified in place, else a new result set
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   337
          is returned and the original is left unmodified
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   338
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   339
        :rtype: `ResultSet`
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   340
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   341
        stop = limit+offset
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   342
        rows = self.rows[offset:stop]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   343
        descr = self.description[offset:stop]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   344
        if inplace:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   345
            rset = self
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   346
            rset.rows, rset.description = rows, descr
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   347
            rset.rowcount = len(rows)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   348
            clear_cache(rset, 'description_struct')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   349
            if offset:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   350
                clear_cache(rset, 'get_entity')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   351
            # we also have to fix/remove from the request entity cache entities
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   352
            # which get a wrong rset reference by this limit call
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   353
            for entity in self.req.cached_entities():
3379
9192ba07890d use .cw_rset instead of rset on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3023
diff changeset
   354
                if entity.cw_rset is self:
4150
2835482b8daf don't try to write .row/.col, use new cw_row/cw_col attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
   355
                    if offset <= entity.cw_row < stop:
2835482b8daf don't try to write .row/.col, use new cw_row/cw_col attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
   356
                        entity.cw_row = entity.cw_row - offset
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   357
                    else:
8048
10a0f73d834d [rset] replace entity cw_rset on .limit(inplace=True) will avoid pb if the entity is still referenced by some other entity relations cache. Closes #2065643
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7595
diff changeset
   358
                        entity.cw_rset = entity.as_rset()
10a0f73d834d [rset] replace entity cw_rset on .limit(inplace=True) will avoid pb if the entity is still referenced by some other entity relations cache. Closes #2065643
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7595
diff changeset
   359
                        entity.cw_row = entity.cw_col = 0
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   360
        else:
3764
034aa14b740a drop _prepare_copy method from rset in favor of a more generic copy method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   361
            rset = self.copy(rows, descr)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   362
            if not offset:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   363
                # can copy built entity caches
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   364
                copy_cache(rset, 'get_entity', self)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   365
        rset.limited = (limit, offset)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   366
        return rset
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1477
diff changeset
   367
10313
ae9e23cf8790 [rset] Deprecate the 'encoded' argument to ResultSet.printable_rql()
Rémi Cardona <remi.cardona@free.fr>
parents: 10187
diff changeset
   368
    def printable_rql(self, encoded=_MARKER):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   369
        """return the result set's origin rql as a string, with arguments
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   370
        substitued
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   371
        """
10313
ae9e23cf8790 [rset] Deprecate the 'encoded' argument to ResultSet.printable_rql()
Rémi Cardona <remi.cardona@free.fr>
parents: 10187
diff changeset
   372
        if encoded is not _MARKER:
ae9e23cf8790 [rset] Deprecate the 'encoded' argument to ResultSet.printable_rql()
Rémi Cardona <remi.cardona@free.fr>
parents: 10187
diff changeset
   373
            warn('[3.21] the "encoded" argument is deprecated', DeprecationWarning)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   374
        encoding = self.req.encoding
10314
8f3783dc6358 Don't pass an encoding to rqlst.as_string()
Julien Cristau <julien.cristau@logilab.fr>
parents: 10313
diff changeset
   375
        rqlstr = self.syntax_tree().as_string(kwargs=self.args)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   376
        # sounds like we get encoded or unicode string due to a bug in as_string
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   377
        if not encoded:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   378
            if isinstance(rqlstr, unicode):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   379
                return rqlstr
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   380
            return unicode(rqlstr, encoding)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1477
diff changeset
   381
        else:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   382
            if isinstance(rqlstr, unicode):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   383
                return rqlstr.encode(encoding)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   384
            return rqlstr
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1477
diff changeset
   385
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   386
    # client helper methods ###################################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   387
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   388
    def entities(self, col=0):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   389
        """iter on entities with eid in the `col` column of the result set"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   390
        for i in xrange(len(self)):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   391
            # may have None values in case of outer join (or aggregat on eid
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   392
            # hacks)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   393
            if self.rows[i][col] is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   394
                yield self.get_entity(i, col)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   395
6857
8d2062387134 [rset] add utility method to get entities and attributes from any rset
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 6225
diff changeset
   396
    def iter_rows_with_entities(self):
8d2062387134 [rset] add utility method to get entities and attributes from any rset
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 6225
diff changeset
   397
        """ iterates over rows, and for each row
8d2062387134 [rset] add utility method to get entities and attributes from any rset
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 6225
diff changeset
   398
        eids are converted to plain entities
8d2062387134 [rset] add utility method to get entities and attributes from any rset
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 6225
diff changeset
   399
        """
8d2062387134 [rset] add utility method to get entities and attributes from any rset
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 6225
diff changeset
   400
        for i, row in enumerate(self):
8d2062387134 [rset] add utility method to get entities and attributes from any rset
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 6225
diff changeset
   401
            _row = []
8d2062387134 [rset] add utility method to get entities and attributes from any rset
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 6225
diff changeset
   402
            for j, col in enumerate(row):
8d2062387134 [rset] add utility method to get entities and attributes from any rset
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 6225
diff changeset
   403
                try:
8d2062387134 [rset] add utility method to get entities and attributes from any rset
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 6225
diff changeset
   404
                    _row.append(self.get_entity(i, j) if col is not None else col)
8d2062387134 [rset] add utility method to get entities and attributes from any rset
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 6225
diff changeset
   405
                except NotAnEntity:
8d2062387134 [rset] add utility method to get entities and attributes from any rset
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 6225
diff changeset
   406
                    _row.append(col)
8d2062387134 [rset] add utility method to get entities and attributes from any rset
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 6225
diff changeset
   407
            yield _row
8d2062387134 [rset] add utility method to get entities and attributes from any rset
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 6225
diff changeset
   408
2792
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   409
    def complete_entity(self, row, col=0, skip_bytes=True):
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   410
        """short cut to get an completed entity instance for a particular
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   411
        row (all instance's attributes have been fetched)
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   412
        """
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   413
        entity = self.get_entity(row, col)
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   414
        entity.complete(skip_bytes=skip_bytes)
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   415
        return entity
135580d15d42 rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   416
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   417
    @cached
4475
37c413a07216 kill most pre 3.2 bw compat code
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4427
diff changeset
   418
    def get_entity(self, row, col):
5312
d2dbba898a96 [doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5311
diff changeset
   419
        """convenience method for query retrieving a single entity, returns a
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   420
        partially initialized Entity instance.
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1477
diff changeset
   421
5314
86e5abbebfaf [doc/book] refresh the autoform section with uicfg content (moved there)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5312
diff changeset
   422
        .. warning::
5312
d2dbba898a96 [doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5311
diff changeset
   423
6859
ace0b991e17b [entity] fix some docstrings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6857
diff changeset
   424
          Due to the cache wrapping this function, you should NEVER give row as
ace0b991e17b [entity] fix some docstrings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6857
diff changeset
   425
          a named parameter (i.e. `rset.get_entity(0, 1)` is OK but
ace0b991e17b [entity] fix some docstrings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6857
diff changeset
   426
          `rset.get_entity(row=0, col=1)` isn't)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   427
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   428
        :type row,col: int, int
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   429
        :param row,col:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   430
          row and col numbers localizing the entity among the result's table
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   431
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   432
        :return: the partially initialized `Entity` instance
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   433
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   434
        etype = self.description[row][col]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   435
        try:
4850
bd640b137f50 [refactor] drop rset.vreg attribute, vreg should be accessed through rset.req. Also kill decorate_rset, simply set rset.req where we were calling this method.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4475
diff changeset
   436
            eschema = self.req.vreg.schema.eschema(etype)
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3625
diff changeset
   437
            if eschema.final:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   438
                raise NotAnEntity(etype)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   439
        except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   440
            raise NotAnEntity(etype)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   441
        return self._build_entity(row, col)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   442
9347
bd841d6ae723 [rset] New method: ResultSet.one()
Christophe de Vienne <cdevienne@gmail.com>
parents: 9331
diff changeset
   443
    def one(self, col=0):
bd841d6ae723 [rset] New method: ResultSet.one()
Christophe de Vienne <cdevienne@gmail.com>
parents: 9331
diff changeset
   444
        """Retrieve exactly one entity from the query.
bd841d6ae723 [rset] New method: ResultSet.one()
Christophe de Vienne <cdevienne@gmail.com>
parents: 9331
diff changeset
   445
bd841d6ae723 [rset] New method: ResultSet.one()
Christophe de Vienne <cdevienne@gmail.com>
parents: 9331
diff changeset
   446
        If the result set is empty, raises :exc:`NoResultError`.
bd841d6ae723 [rset] New method: ResultSet.one()
Christophe de Vienne <cdevienne@gmail.com>
parents: 9331
diff changeset
   447
        If the result set has more than one row, raises
bd841d6ae723 [rset] New method: ResultSet.one()
Christophe de Vienne <cdevienne@gmail.com>
parents: 9331
diff changeset
   448
        :exc:`MultipleResultsError`.
bd841d6ae723 [rset] New method: ResultSet.one()
Christophe de Vienne <cdevienne@gmail.com>
parents: 9331
diff changeset
   449
bd841d6ae723 [rset] New method: ResultSet.one()
Christophe de Vienne <cdevienne@gmail.com>
parents: 9331
diff changeset
   450
        :type col: int
bd841d6ae723 [rset] New method: ResultSet.one()
Christophe de Vienne <cdevienne@gmail.com>
parents: 9331
diff changeset
   451
        :param col: The column localising the entity in the unique row
bd841d6ae723 [rset] New method: ResultSet.one()
Christophe de Vienne <cdevienne@gmail.com>
parents: 9331
diff changeset
   452
bd841d6ae723 [rset] New method: ResultSet.one()
Christophe de Vienne <cdevienne@gmail.com>
parents: 9331
diff changeset
   453
        :return: the partially initialized `Entity` instance
bd841d6ae723 [rset] New method: ResultSet.one()
Christophe de Vienne <cdevienne@gmail.com>
parents: 9331
diff changeset
   454
        """
bd841d6ae723 [rset] New method: ResultSet.one()
Christophe de Vienne <cdevienne@gmail.com>
parents: 9331
diff changeset
   455
        if len(self) == 1:
bd841d6ae723 [rset] New method: ResultSet.one()
Christophe de Vienne <cdevienne@gmail.com>
parents: 9331
diff changeset
   456
            return self.get_entity(0, col)
bd841d6ae723 [rset] New method: ResultSet.one()
Christophe de Vienne <cdevienne@gmail.com>
parents: 9331
diff changeset
   457
        elif len(self) == 0:
bd841d6ae723 [rset] New method: ResultSet.one()
Christophe de Vienne <cdevienne@gmail.com>
parents: 9331
diff changeset
   458
            raise NoResultError("No row was found for one()")
bd841d6ae723 [rset] New method: ResultSet.one()
Christophe de Vienne <cdevienne@gmail.com>
parents: 9331
diff changeset
   459
        else:
bd841d6ae723 [rset] New method: ResultSet.one()
Christophe de Vienne <cdevienne@gmail.com>
parents: 9331
diff changeset
   460
            raise MultipleResultsError("Multiple rows were found for one()")
bd841d6ae723 [rset] New method: ResultSet.one()
Christophe de Vienne <cdevienne@gmail.com>
parents: 9331
diff changeset
   461
2647
b0a2e779845c enable server side entity caching, 25% speedup on codenaf insertion. ALL CW TESTS OK
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2381
diff changeset
   462
    def _build_entity(self, row, col):
6859
ace0b991e17b [entity] fix some docstrings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6857
diff changeset
   463
        """internal method to get a single entity, returns a partially
ace0b991e17b [entity] fix some docstrings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6857
diff changeset
   464
        initialized Entity instance.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   465
6859
ace0b991e17b [entity] fix some docstrings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6857
diff changeset
   466
        partially means that only attributes selected in the RQL query will be
ace0b991e17b [entity] fix some docstrings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6857
diff changeset
   467
        directly assigned to the entity.
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1477
diff changeset
   468
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   469
        :type row,col: int, int
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   470
        :param row,col:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   471
          row and col numbers localizing the entity among the result's table
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   472
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   473
        :return: the partially initialized `Entity` instance
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   474
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   475
        req = self.req
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   476
        if req is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   477
            raise AssertionError('dont call get_entity with no req on the result set')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   478
        rowvalues = self.rows[row]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   479
        eid = rowvalues[col]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   480
        assert eid is not None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   481
        # return cached entity if exists. This also avoids potential recursion
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   482
        # XXX should we consider updating a cached entity with possible
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   483
        #     new attributes found in this resultset ?
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   484
        try:
2648
4ae7d02ce063 F [rset repo cache] set entity.rset when no set on entities retreived from the cache
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2647
diff changeset
   485
            entity = req.entity_cache(eid)
10354
635cfac73d28 [repoapi] fold ClientConnection into Connection
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10314
diff changeset
   486
            entity._cw = req
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   487
        except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   488
            pass
2832
7fb67c54ffb9 [rset] better explanation, refactor try except
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2813
diff changeset
   489
        else:
3379
9192ba07890d use .cw_rset instead of rset on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3023
diff changeset
   490
            if entity.cw_rset is None:
2832
7fb67c54ffb9 [rset] better explanation, refactor try except
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2813
diff changeset
   491
                # entity has no rset set, this means entity has been created by
7fb67c54ffb9 [rset] better explanation, refactor try except
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2813
diff changeset
   492
                # the querier (req is a repository session) and so jas no rset
7fb67c54ffb9 [rset] better explanation, refactor try except
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2813
diff changeset
   493
                # info. Add it.
7fb67c54ffb9 [rset] better explanation, refactor try except
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2813
diff changeset
   494
                entity.cw_rset = self
7fb67c54ffb9 [rset] better explanation, refactor try except
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2813
diff changeset
   495
                entity.cw_row = row
7fb67c54ffb9 [rset] better explanation, refactor try except
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2813
diff changeset
   496
                entity.cw_col = col
7fb67c54ffb9 [rset] better explanation, refactor try except
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2813
diff changeset
   497
            return entity
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   498
        # build entity instance
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   499
        etype = self.description[row][col]
4850
bd640b137f50 [refactor] drop rset.vreg attribute, vreg should be accessed through rset.req. Also kill decorate_rset, simply set rset.req where we were calling this method.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4475
diff changeset
   500
        entity = self.req.vreg['etypes'].etype_class(etype)(req, rset=self,
bd640b137f50 [refactor] drop rset.vreg attribute, vreg should be accessed through rset.req. Also kill decorate_rset, simply set rset.req where we were calling this method.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4475
diff changeset
   501
                                                            row=row, col=col)
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5532
diff changeset
   502
        entity.eid = eid
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   503
        # cache entity
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   504
        req.set_entity_cache(entity)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   505
        # try to complete the entity if there are some additional columns
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   506
        if len(rowvalues) > 1:
7285
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   507
            eschema = entity.e_schema
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   508
            eid_col, attr_cols, rel_cols = self._rset_structure(eschema, col)
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   509
            entity.eid = rowvalues[eid_col]
7968
92303e2ed77a [rset] use .iteritems() instead of items()
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7595
diff changeset
   510
            for attr, col_idx in attr_cols.iteritems():
7285
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   511
                entity.cw_attr_cache[attr] = rowvalues[col_idx]
7968
92303e2ed77a [rset] use .iteritems() instead of items()
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7595
diff changeset
   512
            for (rtype, role), col_idx in rel_cols.iteritems():
7285
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   513
                value = rowvalues[col_idx]
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   514
                if value is None:
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   515
                    if role == 'subject':
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   516
                        rql = 'Any Y WHERE X %s Y, X eid %s'
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   517
                    else:
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   518
                        rql = 'Any Y WHERE Y %s X, X eid %s'
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   519
                    rrset = ResultSet([], rql % (rtype, entity.eid))
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   520
                    rrset.req = req
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   521
                else:
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   522
                    rrset = self._build_entity(row, col_idx).as_rset()
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   523
                entity.cw_set_relation_cache(rtype, role, rrset)
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   524
        return entity
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   525
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   526
    @cached
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   527
    def _rset_structure(self, eschema, entity_col):
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   528
        eid_col = col = entity_col
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   529
        rqlst = self.syntax_tree()
10180
ea10572fccfe [rset] fix crash on displaying rset where some symmetric relation is used. Closes #4739253
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9820
diff changeset
   530
        get_rschema = eschema.schema.rschema
7285
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   531
        attr_cols = {}
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   532
        rel_cols = {}
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   533
        if rqlst.TYPE == 'select':
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   534
            # UNION query, find the subquery from which this entity has been
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   535
            # found
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   536
            select, col = rqlst.locate_subquery(entity_col, eschema.type, self.args)
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   537
        else:
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   538
            select = rqlst
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   539
        # take care, due to outer join support, we may find None
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   540
        # values for non final relation
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   541
        for i, attr, role in attr_desc_iterator(select, col, entity_col):
10180
ea10572fccfe [rset] fix crash on displaying rset where some symmetric relation is used. Closes #4739253
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9820
diff changeset
   542
            rschema = get_rschema(attr)
7285
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   543
            if rschema.final:
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   544
                if attr == 'eid':
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   545
                    eid_col = i
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   546
                else:
7285
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   547
                    attr_cols[attr] = i
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   548
            else:
9820
3ad221fe04aa [entity/rset] replace scary warnings about ambiguous rdefs by XXX in the code
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9780
diff changeset
   549
                # XXX takefirst=True to remove warning triggered by ambiguous relations
3ad221fe04aa [entity/rset] replace scary warnings about ambiguous rdefs by XXX in the code
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9780
diff changeset
   550
                rdef = eschema.rdef(attr, role, takefirst=True)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   551
                # only keep value if it can't be multivalued
3877
7ca53fc72a0a reldefsecurity branch :
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3766
diff changeset
   552
                if rdef.role_cardinality(role) in '1?':
7285
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   553
                    rel_cols[(attr, role)] = i
39437617f3f0 [optim] cache rset column structures
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6915
diff changeset
   554
        return eid_col, attr_cols, rel_cols
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   555
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   556
    @cached
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   557
    def syntax_tree(self):
10087
ed0b076c119b [rset] kill the rset._rqlst cache
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9820
diff changeset
   558
        """return the syntax tree (:class:`rql.stmts.Union`) for the
ed0b076c119b [rset] kill the rset._rqlst cache
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9820
diff changeset
   559
        originating query. You can expect it to have solutions
ed0b076c119b [rset] kill the rset._rqlst cache
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9820
diff changeset
   560
        computed and it will be properly annotated.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   561
        """
10087
ed0b076c119b [rset] kill the rset._rqlst cache
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9820
diff changeset
   562
        return self.req.vreg.parse(self.req, self.rql, self.args)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1477
diff changeset
   563
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   564
    @cached
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   565
    def column_types(self, col):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   566
        """return the list of different types in the column with the given col
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1477
diff changeset
   567
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   568
        :type col: int
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   569
        :param col: the index of the desired column
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   570
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   571
        :rtype: list
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   572
        :return: the different entities type found in the column
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   573
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   574
        return frozenset(struc[-1][col] for struc in self.description_struct())
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   575
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   576
    @cached
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   577
    def description_struct(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   578
        """return a list describing sequence of results with the same
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   579
        description, e.g. :
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   580
        [[0, 4, ('Bug',)]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   581
        [[0, 4, ('Bug',), [5, 8, ('Story',)]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   582
        [[0, 3, ('Project', 'Version',)]]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   583
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   584
        result = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   585
        last = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   586
        for i, row in enumerate(self.description):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   587
            if row != last:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   588
                if last is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   589
                    result[-1][1] = i - 1
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   590
                result.append( [i, None, row] )
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   591
                last = row
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   592
        if last is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   593
            result[-1][1] = i
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   594
        return result
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   595
4427
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   596
    def _locate_query_params(self, rqlst, row, col):
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   597
        locate_query_col = col
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   598
        etype = self.description[row][col]
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   599
        # final type, find a better one to locate the correct subquery
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   600
        # (ambiguous if possible)
4850
bd640b137f50 [refactor] drop rset.vreg attribute, vreg should be accessed through rset.req. Also kill decorate_rset, simply set rset.req where we were calling this method.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4475
diff changeset
   601
        eschema = self.req.vreg.schema.eschema
4427
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   602
        if eschema(etype).final:
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   603
            for select in rqlst.children:
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   604
                try:
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   605
                    myvar = select.selection[col].variable
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   606
                except AttributeError:
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   607
                    # not a variable
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   608
                    continue
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   609
                for i in xrange(len(select.selection)):
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   610
                    if i == col:
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   611
                        continue
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   612
                    coletype = self.description[row][i]
6196
12fdccedab5a cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6195
diff changeset
   613
                    # None description possible on column resulting from an
12fdccedab5a cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6195
diff changeset
   614
                    # outer join
4427
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   615
                    if coletype is None or eschema(coletype).final:
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   616
                        continue
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   617
                    try:
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   618
                        ivar = select.selection[i].variable
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   619
                    except AttributeError:
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   620
                        # not a variable
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   621
                        continue
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   622
                    # check variables don't comes from a subquery or are both
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   623
                    # coming from the same subquery
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   624
                    if getattr(ivar, 'query', None) is getattr(myvar, 'query', None):
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   625
                        etype = coletype
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   626
                        locate_query_col = i
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   627
                        if len(self.column_types(i)) > 1:
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   628
                            return etype, locate_query_col
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   629
        return etype, locate_query_col
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   630
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   631
    @cached
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   632
    def related_entity(self, row, col):
6195
a0c4441e6ddf [rset] add test for #1251252, actually fixed in rql; fix docstring and add comments in rset.related_entity to make things clearer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5752
diff changeset
   633
        """given an cell of the result set, try to return a (entity, relation
a0c4441e6ddf [rset] add test for #1251252, actually fixed in rql; fix docstring and add comments in rset.related_entity to make things clearer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5752
diff changeset
   634
        name) tuple to which this cell is linked.
a0c4441e6ddf [rset] add test for #1251252, actually fixed in rql; fix docstring and add comments in rset.related_entity to make things clearer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5752
diff changeset
   635
a0c4441e6ddf [rset] add test for #1251252, actually fixed in rql; fix docstring and add comments in rset.related_entity to make things clearer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5752
diff changeset
   636
        This is especially useful when the cell is an attribute of an entity,
a0c4441e6ddf [rset] add test for #1251252, actually fixed in rql; fix docstring and add comments in rset.related_entity to make things clearer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5752
diff changeset
   637
        to get the entity to which this attribute belongs to.
a0c4441e6ddf [rset] add test for #1251252, actually fixed in rql; fix docstring and add comments in rset.related_entity to make things clearer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5752
diff changeset
   638
        """
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   639
        rqlst = self.syntax_tree()
6195
a0c4441e6ddf [rset] add test for #1251252, actually fixed in rql; fix docstring and add comments in rset.related_entity to make things clearer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5752
diff changeset
   640
        # UNION query, we've first to find a 'pivot' column to use to get the
a0c4441e6ddf [rset] add test for #1251252, actually fixed in rql; fix docstring and add comments in rset.related_entity to make things clearer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5752
diff changeset
   641
        # actual query from which the row is coming
4427
410c99a917fa fix rset.related_entity with variables coming from subquery while some others not
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   642
        etype, locate_query_col = self._locate_query_params(rqlst, row, col)
6195
a0c4441e6ddf [rset] add test for #1251252, actually fixed in rql; fix docstring and add comments in rset.related_entity to make things clearer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5752
diff changeset
   643
        # now find the query from which this entity has been found. Returned
a0c4441e6ddf [rset] add test for #1251252, actually fixed in rql; fix docstring and add comments in rset.related_entity to make things clearer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5752
diff changeset
   644
        # select node may be a subquery with different column indexes.
3016
5787d1cc8106 [rset] fix #231354 w/ rql 0.22.3 api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   645
        select = rqlst.locate_subquery(locate_query_col, etype, self.args)[0]
6195
a0c4441e6ddf [rset] add test for #1251252, actually fixed in rql; fix docstring and add comments in rset.related_entity to make things clearer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5752
diff changeset
   646
        # then get the index of root query's col in the subquery
3016
5787d1cc8106 [rset] fix #231354 w/ rql 0.22.3 api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   647
        col = rqlst.subquery_selection_index(select, col)
3766
9e5dc4b1ada4 work around a pb. with subquery_selection_index
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3764
diff changeset
   648
        if col is None:
9e5dc4b1ada4 work around a pb. with subquery_selection_index
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3764
diff changeset
   649
            # XXX unexpected, should fix subquery_selection_index ?
9e5dc4b1ada4 work around a pb. with subquery_selection_index
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3764
diff changeset
   650
            return None, None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   651
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   652
            myvar = select.selection[col].variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   653
        except AttributeError:
572
9849fed789c9 test and fix potential error with None optional relation
sylvain.thenault@logilab.fr
parents: 170
diff changeset
   654
            # not a variable
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   655
            return None, None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   656
        rel = myvar.main_relation()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   657
        if rel is not None:
3016
5787d1cc8106 [rset] fix #231354 w/ rql 0.22.3 api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   658
            index = rel.children[0].root_selection_index()
572
9849fed789c9 test and fix potential error with None optional relation
sylvain.thenault@logilab.fr
parents: 170
diff changeset
   659
            if index is not None and self.rows[row][index]:
5667
04cbd80fd5dc [rset] do not break when rset.related_entity(x,y) is not an entity
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 5532
diff changeset
   660
                try:
04cbd80fd5dc [rset] do not break when rset.related_entity(x,y) is not an entity
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 5532
diff changeset
   661
                    entity = self.get_entity(row, index)
04cbd80fd5dc [rset] do not break when rset.related_entity(x,y) is not an entity
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 5532
diff changeset
   662
                    return entity, rel.r_type
8695
358d8bed9626 [toward-py3k] rewrite to "except AnException as exc:" (part of #2711624)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8087
diff changeset
   663
                except NotAnEntity as exc:
5667
04cbd80fd5dc [rset] do not break when rset.related_entity(x,y) is not an entity
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 5532
diff changeset
   664
                    return None, None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   665
        return None, None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   666
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   667
    @cached
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   668
    def searched_text(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   669
        """returns the searched text in case of full-text search
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   670
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   671
        :return: searched text or `None` if the query is not
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   672
                 a full-text query
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   673
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   674
        rqlst = self.syntax_tree()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   675
        for rel in rqlst.iget_nodes(nodes.Relation):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   676
            if rel.r_type == 'has_text':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   677
                __, rhs = rel.get_variable_parts()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   678
                return rhs.eval(self.args)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   679
        return None
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1477
diff changeset
   680
6915
99eb71b311e4 [rset] fix entity building for some result set with UNION and subqueries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6859
diff changeset
   681
def _get_variable(term):
99eb71b311e4 [rset] fix entity building for some result set with UNION and subqueries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6859
diff changeset
   682
    # XXX rewritten const
99eb71b311e4 [rset] fix entity building for some result set with UNION and subqueries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6859
diff changeset
   683
    # use iget_nodes for (hack) case where we have things like MAX(V)
99eb71b311e4 [rset] fix entity building for some result set with UNION and subqueries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6859
diff changeset
   684
    for vref in term.iget_nodes(nodes.VariableRef):
99eb71b311e4 [rset] fix entity building for some result set with UNION and subqueries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6859
diff changeset
   685
        return vref.variable
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   686
6915
99eb71b311e4 [rset] fix entity building for some result set with UNION and subqueries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6859
diff changeset
   687
def attr_desc_iterator(select, selectidx, rootidx):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   688
    """return an iterator on a list of 2-uple (index, attr_relation)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   689
    localizing attribute relations of the main variable in a result's row
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   690
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   691
    :type rqlst: rql.stmts.Select
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   692
    :param rqlst: the RQL syntax tree to describe
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   693
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   694
    :return:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   695
      a generator on (index, relation, target) describing column being
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   696
      attribute of the main variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   697
    """
6915
99eb71b311e4 [rset] fix entity building for some result set with UNION and subqueries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6859
diff changeset
   698
    rootselect = select
99eb71b311e4 [rset] fix entity building for some result set with UNION and subqueries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6859
diff changeset
   699
    while rootselect.parent.parent is not None:
99eb71b311e4 [rset] fix entity building for some result set with UNION and subqueries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6859
diff changeset
   700
        rootselect = rootselect.parent.parent.parent
99eb71b311e4 [rset] fix entity building for some result set with UNION and subqueries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6859
diff changeset
   701
    rootmain = rootselect.selection[selectidx]
99eb71b311e4 [rset] fix entity building for some result set with UNION and subqueries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6859
diff changeset
   702
    rootmainvar = _get_variable(rootmain)
99eb71b311e4 [rset] fix entity building for some result set with UNION and subqueries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6859
diff changeset
   703
    assert rootmainvar
99eb71b311e4 [rset] fix entity building for some result set with UNION and subqueries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6859
diff changeset
   704
    root = rootselect.parent
99eb71b311e4 [rset] fix entity building for some result set with UNION and subqueries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6859
diff changeset
   705
    selectmain = select.selection[selectidx]
99eb71b311e4 [rset] fix entity building for some result set with UNION and subqueries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6859
diff changeset
   706
    for i, term in enumerate(rootselect.selection):
7395
09ffcc04bd21 [rset] close #1683703: rset.get_entity crash on rql query with subquery and aggregat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6915
diff changeset
   707
        try:
09ffcc04bd21 [rset] close #1683703: rset.get_entity crash on rql query with subquery and aggregat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6915
diff changeset
   708
            # don't use _get_variable here: if the term isn't a variable
09ffcc04bd21 [rset] close #1683703: rset.get_entity crash on rql query with subquery and aggregat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6915
diff changeset
   709
            # (function...), we don't want it to be used as an entity attribute
09ffcc04bd21 [rset] close #1683703: rset.get_entity crash on rql query with subquery and aggregat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6915
diff changeset
   710
            # or relation's value (XXX beside MAX/MIN trick?)
09ffcc04bd21 [rset] close #1683703: rset.get_entity crash on rql query with subquery and aggregat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6915
diff changeset
   711
            rootvar = term.variable
09ffcc04bd21 [rset] close #1683703: rset.get_entity crash on rql query with subquery and aggregat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6915
diff changeset
   712
        except AttributeError:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   713
            continue
6915
99eb71b311e4 [rset] fix entity building for some result set with UNION and subqueries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6859
diff changeset
   714
        if rootvar.name == rootmainvar.name:
99eb71b311e4 [rset] fix entity building for some result set with UNION and subqueries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6859
diff changeset
   715
            continue
8085
51929d531aff [rset] fix crash while building entity from rset w/ some subquery. Closes #2089055
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8048
diff changeset
   716
        if select is not rootselect and isinstance(rootvar, nodes.ColumnAlias):
6915
99eb71b311e4 [rset] fix entity building for some result set with UNION and subqueries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6859
diff changeset
   717
            term = select.selection[root.subquery_selection_index(select, i)]
99eb71b311e4 [rset] fix entity building for some result set with UNION and subqueries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6859
diff changeset
   718
        var = _get_variable(term)
99eb71b311e4 [rset] fix entity building for some result set with UNION and subqueries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6859
diff changeset
   719
        if var is None:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   720
            continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   721
        for ref in var.references():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   722
            rel = ref.relation()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   723
            if rel is None or rel.is_types_restriction():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   724
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   725
            lhs, rhs = rel.get_variable_parts()
6915
99eb71b311e4 [rset] fix entity building for some result set with UNION and subqueries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6859
diff changeset
   726
            if selectmain.is_equivalent(lhs):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   727
                if rhs.is_equivalent(term):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   728
                    yield (i, rel.r_type, 'subject')
6915
99eb71b311e4 [rset] fix entity building for some result set with UNION and subqueries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6859
diff changeset
   729
            elif selectmain.is_equivalent(rhs):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   730
                if lhs.is_equivalent(term):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   731
                    yield (i, rel.r_type, 'object')