rqlrewrite.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Tue, 10 Nov 2009 18:06:47 +0100
branchstable
changeset 3815 50b87f759b5d
parent 3689 deb13e88e037
child 3826 0c0c051863cb
permissions -rw-r--r--
test and fix http://www.logilab.org/ticket/499838 refactor nicely on the way
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
     1
"""RQL rewriting utilities : insert rql expression snippets into rql syntax
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
     2
tree.
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
     3
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
     4
This is used for instance for read security checking in the repository.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     5
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     6
:organization: Logilab
1977
606923dff11b big bunch of copyright / docstring update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1802
diff changeset
     7
:copyright: 2007-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     8
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
1977
606923dff11b big bunch of copyright / docstring update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1802
diff changeset
     9
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    10
"""
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    11
__docformat__ = "restructuredtext en"
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    12
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    13
from rql import nodes as n, stmts, TypeResolverException
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    14
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    15
from logilab.common.compat import any
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    16
3437
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    17
from cubicweb import Unauthorized, typed_eid
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    18
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    19
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    20
def add_types_restriction(schema, rqlst, newroot=None, solutions=None):
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    21
    if newroot is None:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    22
        assert solutions is None
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    23
        if hasattr(rqlst, '_types_restr_added'):
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    24
            return
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    25
        solutions = rqlst.solutions
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    26
        newroot = rqlst
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    27
        rqlst._types_restr_added = True
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    28
    else:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    29
        assert solutions is not None
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    30
        rqlst = rqlst.stmt
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    31
    eschema = schema.eschema
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    32
    allpossibletypes = {}
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    33
    for solution in solutions:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    34
        for varname, etype in solution.iteritems():
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3444
diff changeset
    35
            if not varname in newroot.defined_vars or eschema(etype).final:
3437
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    36
                continue
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    37
            allpossibletypes.setdefault(varname, set()).add(etype)
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    38
    for varname in sorted(allpossibletypes):
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    39
        try:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    40
            var = newroot.defined_vars[varname]
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    41
        except KeyError:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    42
            continue
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    43
        stinfo = var.stinfo
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    44
        if stinfo.get('uidrels'):
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    45
            continue # eid specified, no need for additional type specification
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    46
        try:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    47
            typerels = rqlst.defined_vars[varname].stinfo.get('typerels')
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    48
        except KeyError:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    49
            assert varname in rqlst.aliases
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    50
            continue
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    51
        if newroot is rqlst and typerels:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    52
            mytyperel = iter(typerels).next()
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    53
        else:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    54
            for vref in newroot.defined_vars[varname].references():
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    55
                rel = vref.relation()
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    56
                if rel and rel.is_types_restriction():
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    57
                    mytyperel = rel
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    58
                    break
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    59
            else:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    60
                mytyperel = None
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    61
        possibletypes = allpossibletypes[varname]
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    62
        if mytyperel is not None:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    63
            # variable as already some types restriction. new possible types
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    64
            # can only be a subset of existing ones, so only remove no more
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    65
            # possible types
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    66
            for cst in mytyperel.get_nodes(n.Constant):
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    67
                if not cst.value in possibletypes:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    68
                    cst.parent.remove(cst)
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    69
                    try:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    70
                        stinfo['possibletypes'].remove(cst.value)
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    71
                    except KeyError:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    72
                        # restriction on a type not used by this query, may
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    73
                        # occurs with X is IN(...)
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    74
                        pass
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    75
        else:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    76
            # we have to add types restriction
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    77
            if stinfo.get('scope') is not None:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    78
                rel = var.scope.add_type_restriction(var, possibletypes)
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    79
            else:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    80
                # tree is not annotated yet, no scope set so add the restriction
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    81
                # to the root
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    82
                rel = newroot.add_type_restriction(var, possibletypes)
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    83
            stinfo['typerels'] = frozenset((rel,))
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    84
            stinfo['possibletypes'] = possibletypes
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    85
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    86
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    87
def remove_solutions(origsolutions, solutions, defined):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    88
    """when a rqlst has been generated from another by introducing security
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    89
    assertions, this method returns solutions which are contained in orig
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    90
    solutions
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    91
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    92
    newsolutions = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    93
    for origsol in origsolutions:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    94
        for newsol in solutions[:]:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    95
            for var, etype in origsol.items():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    96
                try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    97
                    if newsol[var] != etype:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    98
                        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    99
                            defined[var].stinfo['possibletypes'].remove(newsol[var])
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   100
                        except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   101
                            pass
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   102
                        break
1132
96752791c2b6 pylint cleanup
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   103
                except KeyError:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   104
                    # variable has been rewritten
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   105
                    continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   106
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   107
                newsolutions.append(newsol)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   108
                solutions.remove(newsol)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   109
    return newsolutions
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   110
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   111
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   112
class Unsupported(Exception): pass
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1138
diff changeset
   113
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   114
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   115
class RQLRewriter(object):
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   116
    """insert some rql snippets into another rql syntax tree
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   117
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   118
    this class *isn't thread safe*
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   119
    """
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   120
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   121
    def __init__(self, session):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   122
        self.session = session
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   123
        vreg = session.vreg
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   124
        self.schema = vreg.schema
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   125
        self.annotate = vreg.rqlhelper.annotate
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   126
        self._compute_solutions = vreg.solutions
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   127
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   128
    def compute_solutions(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   129
        self.annotate(self.select)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   130
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   131
            self._compute_solutions(self.session, self.select, self.kwargs)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   132
        except TypeResolverException:
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   133
            raise Unsupported(str(self.select))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   134
        if len(self.select.solutions) < len(self.solutions):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   135
            raise Unsupported()
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1138
diff changeset
   136
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   137
    def rewrite(self, select, snippets, solutions, kwargs):
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   138
        """
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   139
        snippets: (varmap, list of rql expression)
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   140
                  with varmap a *tuple* (select var, snippet var)
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   141
        """
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   142
        self.select = self.insert_scope = select
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   143
        self.solutions = solutions
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   144
        self.kwargs = kwargs
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   145
        self.u_varname = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   146
        self.removing_ambiguity = False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   147
        self.exists_snippet = {}
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   148
        self.pending_keys = []
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   149
        # we have to annotate the rqlst before inserting snippets, even though
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   150
        # we'll have to redo it latter
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   151
        self.annotate(select)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   152
        self.insert_snippets(snippets)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   153
        if not self.exists_snippet and self.u_varname:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   154
            # U has been inserted than cancelled, cleanup
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   155
            select.undefine_variable(select.defined_vars[self.u_varname])
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   156
        # clean solutions according to initial solutions
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   157
        newsolutions = remove_solutions(solutions, select.solutions,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   158
                                        select.defined_vars)
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   159
        assert len(newsolutions) >= len(solutions), (
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   160
            'rewritten rql %s has lost some solutions, there is probably '
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   161
            'something wrong in your schema permission (for instance using a '
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   162
            'RQLExpression which insert a relation which doesn\'t exists in '
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   163
            'the schema)\nOrig solutions: %s\nnew solutions: %s' % (
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   164
            select, solutions, newsolutions))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   165
        if len(newsolutions) > len(solutions):
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   166
            newsolutions = self.remove_ambiguities(snippets, newsolutions)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   167
        select.solutions = newsolutions
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   168
        add_types_restriction(self.schema, select)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1138
diff changeset
   169
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   170
    def insert_snippets(self, snippets, varexistsmap=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   171
        self.rewritten = {}
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   172
        for varmap, rqlexprs in snippets:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   173
            if varexistsmap is not None and not varmap in varexistsmap:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   174
                continue
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   175
            self.varmap = varmap
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   176
            selectvar, snippetvar = varmap
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   177
            assert snippetvar in 'SOX'
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   178
            self.revvarmap = {snippetvar: selectvar}
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   179
            self.varinfo = vi = {}
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   180
            try:
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   181
                vi['const'] = typed_eid(selectvar) # XXX gae
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   182
                vi['rhs_rels'] = vi['lhs_rels'] = {}
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   183
            except ValueError:
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   184
                vi['stinfo'] = sti = self.select.defined_vars[selectvar].stinfo
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   185
                if varexistsmap is None:
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   186
                    vi['rhs_rels'] = dict( (r.r_type, r) for r in sti['rhsrelations'])
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   187
                    vi['lhs_rels'] = dict( (r.r_type, r) for r in sti['relations']
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   188
                                           if not r in sti['rhsrelations'])
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   189
                else:
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   190
                    vi['rhs_rels'] = vi['lhs_rels'] = {}
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   191
            parent = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   192
            inserted = False
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   193
            for rqlexpr in rqlexprs:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   194
                self.current_expr = rqlexpr
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   195
                if varexistsmap is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   196
                    try:
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   197
                        new = self.insert_snippet(varmap, rqlexpr.snippet_rqlst, parent)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   198
                    except Unsupported:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   199
                        continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   200
                    inserted = True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   201
                    if new is not None:
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   202
                        self.exists_snippet[rqlexpr] = new
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   203
                    parent = parent or new
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   204
                else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   205
                    # called to reintroduce snippet due to ambiguity creation,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   206
                    # so skip snippets which are not introducing this ambiguity
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   207
                    exists = varexistsmap[varmap]
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   208
                    if self.exists_snippet[rqlexpr] is exists:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   209
                        self.insert_snippet(varmap, rqlexpr.snippet_rqlst, exists)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   210
            if varexistsmap is None and not inserted:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   211
                # no rql expression found matching rql solutions. User has no access right
3254
fe7ec595751c should not have been commited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3240
diff changeset
   212
                raise Unauthorized()
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1138
diff changeset
   213
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   214
    def insert_snippet(self, varmap, snippetrqlst, parent=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   215
        new = snippetrqlst.where.accept(self)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   216
        if new is not None:
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   217
            if self.varinfo.get('stinfo', {}).get('optrelations'):
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   218
                assert parent is None
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   219
                self.insert_scope = self.snippet_subquery(varmap, new)
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   220
                self.insert_pending()
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   221
                self.insert_scope = self.select
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   222
                return
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   223
            new = n.Exists(new)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   224
            if parent is None:
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   225
                self.insert_scope.add_restriction(new)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   226
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   227
                grandpa = parent.parent
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   228
                or_ = n.Or(parent, new)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   229
                grandpa.replace(parent, or_)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   230
            if not self.removing_ambiguity:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   231
                try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   232
                    self.compute_solutions()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   233
                except Unsupported:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   234
                    # some solutions have been lost, can't apply this rql expr
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   235
                    if parent is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   236
                        self.select.remove_node(new, undefine=True)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   237
                    else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   238
                        parent.parent.replace(or_, or_.children[0])
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   239
                        self._cleanup_inserted(new)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1138
diff changeset
   240
                    raise
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   241
                else:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   242
                    self.insert_scope = new
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   243
                    self.insert_pending()
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   244
                    self.insert_scope = self.select
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   245
            return new
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   246
        self.insert_pending()
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   247
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   248
    def insert_pending(self):
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   249
        """pending_keys hold variable referenced by U has_<action>_permission X
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   250
        relation.
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   251
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   252
        Once the snippet introducing this has been inserted and solutions
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   253
        recomputed, we have to insert snippet defined for <action> of entity
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   254
        types taken by X
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   255
        """
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   256
        while self.pending_keys:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   257
            key, action = self.pending_keys.pop()
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   258
            try:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   259
                varname = self.rewritten[key]
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   260
            except KeyError:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   261
                try:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   262
                    varname = self.revvarmap[key[-1]]
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   263
                except KeyError:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   264
                    # variable isn't used anywhere else, we can't insert security
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   265
                    raise Unauthorized()
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   266
            ptypes = self.select.defined_vars[varname].stinfo['possibletypes']
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   267
            if len(ptypes) > 1:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   268
                # XXX dunno how to handle this
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   269
                self.session.error(
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   270
                    'cant check security of %s, ambigous type for %s in %s',
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   271
                    self.select, varname, key[0]) # key[0] == the rql expression
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   272
                raise Unauthorized()
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   273
            etype = iter(ptypes).next()
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   274
            eschema = self.schema.eschema(etype)
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   275
            if not eschema.has_perm(self.session, action):
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   276
                rqlexprs = eschema.get_rqlexprs(action)
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   277
                if not rqlexprs:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   278
                    raise Unauthorised()
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   279
                self.insert_snippets([((varname, 'X'), rqlexprs)])
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   280
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   281
    def snippet_subquery(self, varmap, transformedsnippet):
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   282
        """introduce the given snippet in a subquery"""
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   283
        subselect = stmts.Select()
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   284
        selectvar, snippetvar = varmap
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   285
        subselect.append_selected(n.VariableRef(
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   286
            subselect.get_variable(selectvar)))
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   287
        aliases = [selectvar]
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   288
        subselect.add_restriction(transformedsnippet.copy(subselect))
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   289
        stinfo = self.varinfo['stinfo']
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   290
        for rel in stinfo['relations']:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   291
            rschema = self.schema.rschema(rel.r_type)
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3444
diff changeset
   292
            if rschema.final or (rschema.inlined and
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   293
                                      not rel in stinfo['rhsrelations']):
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   294
                self.select.remove_node(rel)
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   295
                rel.children[0].name = selectvar
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   296
                subselect.add_restriction(rel.copy(subselect))
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   297
                for vref in rel.children[1].iget_nodes(n.VariableRef):
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   298
                    subselect.append_selected(vref.copy(subselect))
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   299
                    aliases.append(vref.name)
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   300
        if self.u_varname:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   301
            # generate an identifier for the substitution
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   302
            argname = subselect.allocate_varname()
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   303
            while argname in self.kwargs:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   304
                argname = subselect.allocate_varname()
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   305
            subselect.add_constant_restriction(subselect.get_variable(self.u_varname),
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   306
                                               'eid', unicode(argname), 'Substitute')
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   307
            self.kwargs[argname] = self.session.user.eid
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   308
        add_types_restriction(self.schema, subselect, subselect,
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   309
                              solutions=self.solutions)
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   310
        myunion = stmts.Union()
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   311
        myunion.append(subselect)
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   312
        aliases = [n.VariableRef(self.select.get_variable(name, i))
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   313
                   for i, name in enumerate(aliases)]
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   314
        self.select.add_subquery(n.SubQuery(aliases, myunion), check=False)
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   315
        self._cleanup_inserted(transformedsnippet)
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   316
        try:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   317
            self.compute_solutions()
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   318
        except Unsupported:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   319
            # some solutions have been lost, can't apply this rql expr
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   320
            self.select.remove_subquery(new, undefine=True)
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   321
            raise
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   322
        return subselect
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   323
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   324
    def remove_ambiguities(self, snippets, newsolutions):
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   325
        # the snippet has introduced some ambiguities, we have to resolve them
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   326
        # "manually"
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   327
        variantes = self.build_variantes(newsolutions)
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   328
        # insert "is" where necessary
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   329
        varexistsmap = {}
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   330
        self.removing_ambiguity = True
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   331
        for (erqlexpr, varmap, oldvarname), etype in variantes[0].iteritems():
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   332
            varname = self.rewritten[(erqlexpr, varmap, oldvarname)]
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   333
            var = self.select.defined_vars[varname]
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   334
            exists = var.references()[0].scope
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   335
            exists.add_constant_restriction(var, 'is', etype, 'etype')
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   336
            varexistsmap[varmap] = exists
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   337
        # insert ORED exists where necessary
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   338
        for variante in variantes[1:]:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   339
            self.insert_snippets(snippets, varexistsmap)
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   340
            for key, etype in variante.iteritems():
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   341
                varname = self.rewritten[key]
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   342
                try:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   343
                    var = self.select.defined_vars[varname]
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   344
                except KeyError:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   345
                    # not a newly inserted variable
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   346
                    continue
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   347
                exists = var.references()[0].scope
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   348
                exists.add_constant_restriction(var, 'is', etype, 'etype')
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   349
        # recompute solutions
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   350
        #select.annotated = False # avoid assertion error
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   351
        self.compute_solutions()
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   352
        # clean solutions according to initial solutions
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   353
        return remove_solutions(self.solutions, self.select.solutions,
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   354
                                self.select.defined_vars)
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   355
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   356
    def build_variantes(self, newsolutions):
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   357
        variantes = set()
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   358
        for sol in newsolutions:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   359
            variante = []
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   360
            for key, newvar in self.rewritten.iteritems():
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   361
                variante.append( (key, sol[newvar]) )
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   362
            variantes.add(tuple(variante))
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   363
        # rebuild variantes as dict
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   364
        variantes = [dict(variante) for variante in variantes]
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   365
        # remove variable which have always the same type
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   366
        for key in self.rewritten:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   367
            it = iter(variantes)
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   368
            etype = it.next()[key]
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   369
            for variante in it:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   370
                if variante[key] != etype:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   371
                    break
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   372
            else:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   373
                for variante in variantes:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   374
                    del variante[key]
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   375
        return variantes
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   376
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   377
    def _cleanup_inserted(self, node):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   378
        # cleanup inserted variable references
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   379
        for vref in node.iget_nodes(n.VariableRef):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   380
            vref.unregister_reference()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   381
            if not vref.variable.stinfo['references']:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   382
                # no more references, undefine the variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   383
                del self.select.defined_vars[vref.name]
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1138
diff changeset
   384
3443
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   385
    def _may_be_shared_with(self, sniprel, target, searchedvarname):
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   386
        """if the snippet relation can be skipped to use a relation from the
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   387
        original query, return that relation node
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   388
        """
3443
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   389
        rschema = self.schema.rschema(sniprel.r_type)
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   390
        try:
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   391
            if target == 'object':
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   392
                orel = self.varinfo['lhs_rels'][sniprel.r_type]
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   393
                cardindex = 0
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   394
                ttypes_func = rschema.objects
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   395
                rprop = rschema.rproperty
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   396
            else: # target == 'subject':
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   397
                orel = self.varinfo['rhs_rels'][sniprel.r_type]
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   398
                cardindex = 1
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   399
                ttypes_func = rschema.subjects
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   400
                rprop = lambda x, y, z: rschema.rproperty(y, x, z)
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   401
        except KeyError, ex:
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   402
            # may be raised by self.varinfo['xhs_rels'][sniprel.r_type]
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   403
            return None
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   404
        # can't share neged relation or relations with different outer join
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   405
        if (orel.neged(strict=True) or sniprel.neged(strict=True)
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   406
            or (orel.optional and orel.optional != sniprel.optional)):
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   407
            return None
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   408
        # if cardinality is in '?1', we can ignore the snippet relation and use
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   409
        # variable from the original query
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   410
        for etype in self.varinfo['stinfo']['possibletypes']:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   411
            for ttype in ttypes_func(etype):
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   412
                if rprop(etype, ttype, 'cardinality')[cardindex] in '+*':
3443
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   413
                    return None
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   414
        return orel
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   415
3443
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   416
    def _use_orig_term(self, snippet_varname, term):
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   417
        key = (self.current_expr, self.varmap, snippet_varname)
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   418
        if key in self.rewritten:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   419
            insertedvar = self.select.defined_vars.pop(self.rewritten[key])
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   420
            for inserted_vref in insertedvar.references():
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   421
                inserted_vref.parent.replace(inserted_vref, term.copy(self.select))
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   422
        self.rewritten[key] = term.name
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   423
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   424
    def _get_varname_or_term(self, vname):
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   425
        if vname == 'U':
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   426
            if self.u_varname is None:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   427
                select = self.select
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   428
                self.u_varname = select.allocate_varname()
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   429
                # generate an identifier for the substitution
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   430
                argname = select.allocate_varname()
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   431
                while argname in self.kwargs:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   432
                    argname = select.allocate_varname()
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   433
                # insert "U eid %(u)s"
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   434
                var = select.get_variable(self.u_varname)
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   435
                select.add_constant_restriction(select.get_variable(self.u_varname),
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   436
                                                'eid', unicode(argname), 'Substitute')
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   437
                self.kwargs[argname] = self.session.user.eid
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   438
            return self.u_varname
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   439
        key = (self.current_expr, self.varmap, vname)
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   440
        try:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   441
            return self.rewritten[key]
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   442
        except KeyError:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   443
            self.rewritten[key] = newvname = self.select.allocate_varname()
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   444
            return newvname
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   445
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   446
    # visitor methods ##########################################################
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   447
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   448
    def _visit_binary(self, node, cls):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   449
        newnode = cls()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   450
        for c in node.children:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   451
            new = c.accept(self)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   452
            if new is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   453
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   454
            newnode.append(new)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   455
        if len(newnode.children) == 0:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   456
            return None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   457
        if len(newnode.children) == 1:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   458
            return newnode.children[0]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   459
        return newnode
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   460
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   461
    def _visit_unary(self, node, cls):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   462
        newc = node.children[0].accept(self)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   463
        if newc is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   464
            return None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   465
        newnode = cls()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   466
        newnode.append(newc)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1138
diff changeset
   467
        return newnode
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1138
diff changeset
   468
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   469
    def visit_and(self, node):
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   470
        return self._visit_binary(node, n.And)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   471
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   472
    def visit_or(self, node):
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   473
        return self._visit_binary(node, n.Or)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1138
diff changeset
   474
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   475
    def visit_not(self, node):
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   476
        return self._visit_unary(node, n.Not)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   477
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   478
    def visit_exists(self, node):
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   479
        return self._visit_unary(node, n.Exists)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1138
diff changeset
   480
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   481
    def visit_relation(self, node):
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   482
        lhs, rhs = node.get_variable_parts()
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   483
        if node.r_type in ('has_add_permission', 'has_update_permission',
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   484
                           'has_delete_permission', 'has_read_permission'):
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   485
            assert lhs.name == 'U'
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   486
            action = node.r_type.split('_')[1]
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   487
            key = (self.current_expr, self.varmap, rhs.name)
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   488
            self.pending_keys.append( (key, action) )
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   489
            return
3443
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   490
        if isinstance(rhs, n.VariableRef):
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   491
            if lhs.name in self.revvarmap and rhs.name != 'U':
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   492
                orel = self._may_be_shared_with(node, 'object', lhs.name)
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   493
                if orel is not None:
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   494
                    self._use_orig_term(rhs.name, orel.children[1].children[0])
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   495
                    return
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   496
            elif rhs.name in self.revvarmap and lhs.name != 'U':
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   497
                orel = self._may_be_shared_with(node, 'subject', rhs.name)
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   498
                if orel is not None:
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   499
                    self._use_orig_term(lhs.name, orel.children[0])
34e451da9b5d [security] test and fix/refactor optimization of optional varialbe when rewriting rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   500
                    return
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   501
        rel = n.Relation(node.r_type, node.optional)
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   502
        for c in node.children:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   503
            rel.append(c.accept(self))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   504
        return rel
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   505
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   506
    def visit_comparison(self, node):
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   507
        cmp_ = n.Comparison(node.operator)
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   508
        for c in node.children:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   509
            cmp_.append(c.accept(self))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   510
        return cmp_
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   511
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   512
    def visit_mathexpression(self, node):
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   513
        cmp_ = n.MathExpression(node.operator)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   514
        for c in cmp.children:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   515
            cmp_.append(c.accept(self))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   516
        return cmp_
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1138
diff changeset
   517
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   518
    def visit_function(self, node):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   519
        """generate filter name for a function"""
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   520
        function_ = n.Function(node.name)
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   521
        for c in node.children:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   522
            function_.append(c.accept(self))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   523
        return function_
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   524
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   525
    def visit_constant(self, node):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   526
        """generate filter name for a constant"""
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   527
        return n.Constant(node.value, node.type)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   528
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   529
    def visit_variableref(self, node):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   530
        """get the sql name for a variable reference"""
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   531
        if node.name in self.revvarmap:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   532
            if self.varinfo.get('const') is not None:
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   533
                return n.Constant(self.varinfo['const'], 'Int') # XXX gae
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   534
            return n.VariableRef(self.select.get_variable(
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   535
                self.revvarmap[node.name]))
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   536
        vname_or_term = self._get_varname_or_term(node.name)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   537
        if isinstance(vname_or_term, basestring):
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   538
            return n.VariableRef(self.select.get_variable(vname_or_term))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   539
        # shared term
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   540
        return vname_or_term.copy(self.select)