rqlrewrite.py
author Julien Cristau <julien.cristau@logilab.fr>
Tue, 17 Jan 2012 11:49:23 +0100
changeset 8171 6dececcaf454
parent 8147 335b358c7017
child 8264 a4b009ba92ce
permissions -rw-r--r--
[datafeed] Don't pretend all columns are sortable in datafeed sources import log view. Closes #2146387
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
7138
9aba650eea6b [rql rewriter] drop unused argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7137
diff changeset
     1
# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
5421
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4908
diff changeset
     2
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4908
diff changeset
     3
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4908
diff changeset
     4
# This file is part of CubicWeb.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4908
diff changeset
     5
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4908
diff changeset
     6
# CubicWeb is free software: you can redistribute it and/or modify it under the
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4908
diff changeset
     7
# terms of the GNU Lesser General Public License as published by the Free
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4908
diff changeset
     8
# Software Foundation, either version 2.1 of the License, or (at your option)
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4908
diff changeset
     9
# any later version.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4908
diff changeset
    10
#
5424
8ecbcbff9777 replace logilab-common by CubicWeb in disclaimer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5421
diff changeset
    11
# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
5421
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4908
diff changeset
    12
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4908
diff changeset
    13
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4908
diff changeset
    14
# details.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4908
diff changeset
    15
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4908
diff changeset
    16
# You should have received a copy of the GNU Lesser General Public License along
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4908
diff changeset
    17
# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
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
    18
"""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
    19
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
    20
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    21
This is used for instance for read security checking in the repository.
5992
5f9a9086c171 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5704
diff changeset
    22
"""
7535
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
    23
from __future__ import with_statement
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    24
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
    25
__docformat__ = "restructuredtext en"
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    26
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
    27
from rql import nodes as n, stmts, TypeResolverException
7139
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
    28
from rql.utils import common_parent
7535
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
    29
4908
b3ad329cbe17 [rql rewrite] until a better solution is found raise BadSchemaDefinition when two inlined relations with security on an optional variable is used, explaining how to bypass it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4907
diff changeset
    30
from yams import BadSchemaDefinition
7535
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
    31
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
    32
from logilab.common import tempattr
3826
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
    33
from logilab.common.graph import has_path
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
    34
3437
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    35
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
    36
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    37
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    38
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
    39
    if newroot is None:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    40
        assert solutions is None
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    41
        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
    42
            return
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    43
        solutions = rqlst.solutions
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    44
        newroot = rqlst
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    45
        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
    46
    else:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    47
        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
    48
        rqlst = rqlst.stmt
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    49
    eschema = schema.eschema
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    50
    allpossibletypes = {}
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    51
    for solution in solutions:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    52
        for varname, etype in solution.iteritems():
6123
0d0a87e88281 [querier] add_types_restriction_cleanups: remove useless try/except (we already filtered out variables not in newroot.defined_vars) and dict accss. Also systematically set computed solutions instead of modifying existing ones
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5992
diff changeset
    53
            # XXX not considering aliases by design, right ?
0d0a87e88281 [querier] add_types_restriction_cleanups: remove useless try/except (we already filtered out variables not in newroot.defined_vars) and dict accss. Also systematically set computed solutions instead of modifying existing ones
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5992
diff changeset
    54
            if varname not 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
    55
                continue
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    56
            allpossibletypes.setdefault(varname, set()).add(etype)
8074
a7f76e322659 add some notes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8056
diff changeset
    57
    # XXX could be factorized with add_etypes_restriction from rql 0.31
3437
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    58
    for varname in sorted(allpossibletypes):
6123
0d0a87e88281 [querier] add_types_restriction_cleanups: remove useless try/except (we already filtered out variables not in newroot.defined_vars) and dict accss. Also systematically set computed solutions instead of modifying existing ones
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5992
diff changeset
    59
        var = newroot.defined_vars[varname]
3437
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    60
        stinfo = var.stinfo
5004
4cc020ee70e2 le patch rql26 a été importé
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4908
diff changeset
    61
        if stinfo.get('uidrel') is not None:
3437
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    62
            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
    63
        try:
5004
4cc020ee70e2 le patch rql26 a été importé
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4908
diff changeset
    64
            typerel = rqlst.defined_vars[varname].stinfo.get('typerel')
3437
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    65
        except KeyError:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    66
            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
    67
            continue
5004
4cc020ee70e2 le patch rql26 a été importé
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4908
diff changeset
    68
        if newroot is rqlst and typerel is not None:
4cc020ee70e2 le patch rql26 a été importé
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4908
diff changeset
    69
            mytyperel = typerel
3437
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    70
        else:
6123
0d0a87e88281 [querier] add_types_restriction_cleanups: remove useless try/except (we already filtered out variables not in newroot.defined_vars) and dict accss. Also systematically set computed solutions instead of modifying existing ones
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5992
diff changeset
    71
            for vref in var.references():
3437
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    72
                rel = vref.relation()
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    73
                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
    74
                    mytyperel = rel
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    75
                    break
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    76
            else:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    77
                mytyperel = None
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    78
        possibletypes = allpossibletypes[varname]
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    79
        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
    80
            # 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
    81
            # 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
    82
            # possible types
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    83
            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
    84
                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
    85
                    cst.parent.remove(cst)
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    86
        else:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    87
            # 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
    88
            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
    89
                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
    90
            else:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    91
                # 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
    92
                # to the root
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    93
                rel = newroot.add_type_restriction(var, possibletypes)
5004
4cc020ee70e2 le patch rql26 a été importé
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4908
diff changeset
    94
            stinfo['typerel'] = rel
6123
0d0a87e88281 [querier] add_types_restriction_cleanups: remove useless try/except (we already filtered out variables not in newroot.defined_vars) and dict accss. Also systematically set computed solutions instead of modifying existing ones
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5992
diff changeset
    95
        stinfo['possibletypes'] = possibletypes
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    96
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
    97
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    98
def remove_solutions(origsolutions, solutions, defined):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    99
    """when a rqlst has been generated from another by introducing security
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   100
    assertions, this method returns solutions which are contained in orig
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   101
    solutions
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   102
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   103
    newsolutions = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   104
    for origsol in origsolutions:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   105
        for newsol in solutions[:]:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   106
            for var, etype in origsol.items():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   107
                try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   108
                    if newsol[var] != etype:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   109
                        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   110
                            defined[var].stinfo['possibletypes'].remove(newsol[var])
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   111
                        except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   112
                            pass
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   113
                        break
1132
96752791c2b6 pylint cleanup
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   114
                except KeyError:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   115
                    # variable has been rewritten
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   116
                    continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   117
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   118
                newsolutions.append(newsol)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   119
                solutions.remove(newsol)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   120
    return newsolutions
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   121
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
   122
7850
d14b77c42b06 [test] sort to avoid random failure due to dict order
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7843
diff changeset
   123
def iter_relations(stinfo):
d14b77c42b06 [test] sort to avoid random failure due to dict order
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7843
diff changeset
   124
    # this is a function so that test may return relation in a predictable order
d14b77c42b06 [test] sort to avoid random failure due to dict order
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7843
diff changeset
   125
    return stinfo['relations'] - stinfo['rhsrelations']
d14b77c42b06 [test] sort to avoid random failure due to dict order
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7843
diff changeset
   126
4721
8f63691ccb7f pylint style fixes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4719
diff changeset
   127
class Unsupported(Exception):
8f63691ccb7f pylint style fixes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4719
diff changeset
   128
    """raised when an rql expression can't be inserted in some rql query
8f63691ccb7f pylint style fixes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4719
diff changeset
   129
    because it create an unresolvable query (eg no solutions found)
8f63691ccb7f pylint style fixes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4719
diff changeset
   130
    """
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1138
diff changeset
   131
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
   132
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   133
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
   134
    """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
   135
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   136
    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
   137
    """
8604a15995d1 refactor so that rql rewriter may be 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
    def __init__(self, session):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   140
        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
   141
        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
   142
        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
   143
        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
   144
        self._compute_solutions = vreg.solutions
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   145
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   146
    def compute_solutions(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   147
        self.annotate(self.select)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   148
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   149
            self._compute_solutions(self.session, self.select, self.kwargs)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   150
        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
   151
            raise Unsupported(str(self.select))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   152
        if len(self.select.solutions) < len(self.solutions):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   153
            raise Unsupported()
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1138
diff changeset
   154
3826
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   155
    def rewrite(self, select, snippets, solutions, kwargs, existingvars=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
   156
        """
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   157
        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
   158
                  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
   159
        """
5582
3e133b29a1a4 [rql2sql] follow rql 0.26.1 changes: NOT nodes normalization, allowing simplification of sql generation, and fix #XXX
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   160
        self.select = select
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   161
        self.solutions = solutions
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   162
        self.kwargs = kwargs
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   163
        self.u_varname = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   164
        self.removing_ambiguity = False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   165
        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
   166
        self.pending_keys = []
3826
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   167
        self.existingvars = existingvars
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   168
        # we have to annotate the rqlst before inserting snippets, even though
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   169
        # we'll have to redo it latter
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   170
        self.annotate(select)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   171
        self.insert_snippets(snippets)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   172
        if not self.exists_snippet and self.u_varname:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   173
            # U has been inserted than cancelled, cleanup
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   174
            select.undefine_variable(select.defined_vars[self.u_varname])
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   175
        # clean solutions according to initial solutions
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   176
        newsolutions = remove_solutions(solutions, select.solutions,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   177
                                        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
   178
        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
   179
            '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
   180
            '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
   181
            '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
   182
            '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
   183
            select, solutions, newsolutions))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   184
        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
   185
            newsolutions = self.remove_ambiguities(snippets, newsolutions)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   186
        select.solutions = newsolutions
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   187
        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
   188
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   189
    def insert_snippets(self, snippets, varexistsmap=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   190
        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
   191
        for varmap, rqlexprs in snippets:
7139
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   192
            if isinstance(varmap, dict):
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   193
                varmap = tuple(sorted(varmap.items()))
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   194
            else:
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   195
                assert isinstance(varmap, tuple), varmap
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
   196
            if varexistsmap is not None and not varmap in varexistsmap:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   197
                continue
7139
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   198
            self.insert_varmap_snippets(varmap, rqlexprs, varexistsmap)
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   199
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   200
    def insert_varmap_snippets(self, varmap, rqlexprs, varexistsmap):
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   201
        self.varmap = varmap
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   202
        self.revvarmap = {}
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   203
        self.varinfos = []
7535
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   204
        self._insert_scope = None
7139
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   205
        for i, (selectvar, snippetvar) in enumerate(varmap):
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
   206
            assert snippetvar in 'SOX'
7139
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   207
            self.revvarmap[snippetvar] = (selectvar, i)
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   208
            vi = {}
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   209
            self.varinfos.append(vi)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   210
            try:
8056
8909800a8c51 [cleanup] drop some appengine support junk
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7879
diff changeset
   211
                vi['const'] = typed_eid(selectvar)
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
   212
                vi['rhs_rels'] = vi['lhs_rels'] = {}
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   213
            except ValueError:
4906
9a50539f01d1 [rql rewriting] handle case where we want to insert snippet on a variable that has previously been moved to a subquery
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4721
diff changeset
   214
                try:
9a50539f01d1 [rql rewriting] handle case where we want to insert snippet on a variable that has previously been moved to a subquery
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4721
diff changeset
   215
                    vi['stinfo'] = sti = self.select.defined_vars[selectvar].stinfo
9a50539f01d1 [rql rewriting] handle case where we want to insert snippet on a variable that has previously been moved to a subquery
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4721
diff changeset
   216
                except KeyError:
7139
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   217
                    # variable may have been moved to a newly inserted subquery
4906
9a50539f01d1 [rql rewriting] handle case where we want to insert snippet on a variable that has previously been moved to a subquery
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4721
diff changeset
   218
                    # we should insert snippet in that subquery
9a50539f01d1 [rql rewriting] handle case where we want to insert snippet on a variable that has previously been moved to a subquery
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4721
diff changeset
   219
                    subquery = self.select.aliases[selectvar].query
9a50539f01d1 [rql rewriting] handle case where we want to insert snippet on a variable that has previously been moved to a subquery
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4721
diff changeset
   220
                    assert len(subquery.children) == 1
9a50539f01d1 [rql rewriting] handle case where we want to insert snippet on a variable that has previously been moved to a subquery
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4721
diff changeset
   221
                    subselect = subquery.children[0]
9a50539f01d1 [rql rewriting] handle case where we want to insert snippet on a variable that has previously been moved to a subquery
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4721
diff changeset
   222
                    RQLRewriter(self.session).rewrite(subselect, [(varmap, rqlexprs)],
9a50539f01d1 [rql rewriting] handle case where we want to insert snippet on a variable that has previously been moved to a subquery
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4721
diff changeset
   223
                                                      subselect.solutions, self.kwargs)
7139
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   224
                    return
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   225
                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
   226
                    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
   227
                    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
   228
                                           if not r in sti['rhsrelations'])
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   229
                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
   230
                    vi['rhs_rels'] = vi['lhs_rels'] = {}
7139
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   231
        parent = None
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   232
        inserted = False
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   233
        for rqlexpr in rqlexprs:
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   234
            self.current_expr = rqlexpr
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   235
            if varexistsmap is None:
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   236
                try:
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   237
                    new = self.insert_snippet(varmap, rqlexpr.snippet_rqlst, parent)
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   238
                except Unsupported:
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   239
                    continue
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   240
                inserted = True
7535
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   241
                if new is not None and self._insert_scope is None:
7139
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   242
                    self.exists_snippet[rqlexpr] = new
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   243
                parent = parent or new
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   244
            else:
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   245
                # called to reintroduce snippet due to ambiguity creation,
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   246
                # so skip snippets which are not introducing this ambiguity
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   247
                exists = varexistsmap[varmap]
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   248
                if self.exists_snippet[rqlexpr] is exists:
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   249
                    self.insert_snippet(varmap, rqlexpr.snippet_rqlst, exists)
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   250
        if varexistsmap is None and not inserted:
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   251
            # no rql expression found matching rql solutions. User has no access right
8112
d3f1e28d5bdb [rqlrewrite] fix comment
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8074
diff changeset
   252
            raise Unauthorized() # XXX may also be because of bad constraints in schema definition
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1138
diff changeset
   253
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
   254
    def insert_snippet(self, varmap, snippetrqlst, parent=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   255
        new = snippetrqlst.where.accept(self)
3826
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   256
        existing = self.existingvars
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   257
        self.existingvars = None
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   258
        try:
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   259
            return self._insert_snippet(varmap, parent, new)
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   260
        finally:
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   261
            self.existingvars = existing
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   262
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   263
    def _insert_snippet(self, varmap, parent, new):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   264
        if new is not None:
5582
3e133b29a1a4 [rql2sql] follow rql 0.26.1 changes: NOT nodes normalization, allowing simplification of sql generation, and fix #XXX
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   265
            if self._insert_scope is None:
7139
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   266
                insert_scope = None
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   267
                for vi in self.varinfos:
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   268
                    scope = vi.get('stinfo', {}).get('scope', self.select)
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   269
                    if insert_scope is None:
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   270
                        insert_scope = scope
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   271
                    else:
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   272
                        insert_scope = common_parent(scope, insert_scope)
5582
3e133b29a1a4 [rql2sql] follow rql 0.26.1 changes: NOT nodes normalization, allowing simplification of sql generation, and fix #XXX
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   273
            else:
3e133b29a1a4 [rql2sql] follow rql 0.26.1 changes: NOT nodes normalization, allowing simplification of sql generation, and fix #XXX
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   274
                insert_scope = self._insert_scope
7535
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   275
            if self._insert_scope is None and any(vi.get('stinfo', {}).get('optrelations')
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   276
                                                  for vi in self.varinfos):
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
   277
                assert parent is None
5582
3e133b29a1a4 [rql2sql] follow rql 0.26.1 changes: NOT nodes normalization, allowing simplification of sql generation, and fix #XXX
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   278
                self._insert_scope = self.snippet_subquery(varmap, 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
   279
                self.insert_pending()
7535
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   280
                #self._insert_scope = 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
   281
                return
7137
01b23ec9c066 [rql rewriter] don't add unnecessary (potentially buggy) exists
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6123
diff changeset
   282
            if not isinstance(new, (n.Exists, n.Not)):
01b23ec9c066 [rql rewriter] don't add unnecessary (potentially buggy) exists
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6123
diff changeset
   283
                new = n.Exists(new)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   284
            if parent is None:
5582
3e133b29a1a4 [rql2sql] follow rql 0.26.1 changes: NOT nodes normalization, allowing simplification of sql generation, and fix #XXX
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   285
                insert_scope.add_restriction(new)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   286
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   287
                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
   288
                or_ = n.Or(parent, new)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   289
                grandpa.replace(parent, or_)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   290
            if not self.removing_ambiguity:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   291
                try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   292
                    self.compute_solutions()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   293
                except Unsupported:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   294
                    # some solutions have been lost, can't apply this rql expr
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   295
                    if parent is None:
7535
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   296
                        self.current_statement().remove_node(new, undefine=True)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   297
                    else:
8147
335b358c7017 [rql, security] fix buggy rqlstr cleanup when some introduced snippet create an unresolvable query. Closes #2142041
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8112
diff changeset
   298
                        grandpa.replace(or_, parent)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   299
                        self._cleanup_inserted(new)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1138
diff changeset
   300
                    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
   301
                else:
7535
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   302
                    with tempattr(self, '_insert_scope', new):
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   303
                        self.insert_pending()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   304
            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
   305
        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
   306
8604a15995d1 refactor so that rql rewriter may be 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
    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
   308
        """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
   309
        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
   310
8604a15995d1 refactor so that rql rewriter may be 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
        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
   312
        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
   313
        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
   314
        """
7535
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   315
        stmt = self.current_statement()
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
   316
        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
   317
            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
   318
            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
   319
                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
   320
            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
   321
                try:
7139
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   322
                    varname = self.revvarmap[key[-1]][0]
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
   323
                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
   324
                    # 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
   325
                    raise Unauthorized()
7535
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   326
            ptypes = stmt.defined_vars[varname].stinfo['possibletypes']
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
   327
            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
   328
                # 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
   329
                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
   330
                    'cant check security of %s, ambigous type for %s in %s',
7535
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   331
                    stmt, varname, key[0]) # key[0] == the rql expression
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
   332
                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
   333
            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
   334
            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
   335
            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
   336
                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
   337
                if not rqlexprs:
3934
d9a29a1fbe43 bugfix typo in exception name
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 3826
diff changeset
   338
                    raise Unauthorized()
7139
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   339
                self.insert_snippets([({varname: 'X'}, rqlexprs)])
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
   340
8604a15995d1 refactor so that rql rewriter may be 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
    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
   342
        """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
   343
        subselect = stmts.Select()
4907
e623afd49356 [rql rewriting] handle case where we've and optional inlined relation in the original query. Also, we should append EXISTS even in subquery to avoid inserting duplicates in results
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4906
diff changeset
   344
        snippetrqlst = n.Exists(transformedsnippet.copy(subselect))
7843
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   345
        get_rschema = self.schema.rschema
7139
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   346
        aliases = []
7843
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   347
        done = set()
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   348
        for i, (selectvar, _) in enumerate(varmap):
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   349
            need_null_test = False
7139
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   350
            subselectvar = subselect.get_variable(selectvar)
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   351
            subselect.append_selected(n.VariableRef(subselectvar))
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   352
            aliases.append(selectvar)
7843
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   353
            todo = [(selectvar, self.varinfos[i]['stinfo'])]
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   354
            while todo:
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   355
                varname, stinfo = todo.pop()
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   356
                done.add(varname)
7850
d14b77c42b06 [test] sort to avoid random failure due to dict order
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7843
diff changeset
   357
                for rel in iter_relations(stinfo):
7843
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   358
                    if rel in done:
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   359
                        continue
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   360
                    done.add(rel)
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   361
                    rschema = get_rschema(rel.r_type)
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   362
                    if rschema.final or rschema.inlined:
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   363
                        rel.children[0].name = varname # XXX explain why
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   364
                        subselect.add_restriction(rel.copy(subselect))
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   365
                        for vref in rel.children[1].iget_nodes(n.VariableRef):
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   366
                            if isinstance(vref.variable, n.ColumnAlias):
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   367
                                # XXX could probably be handled by generating the
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   368
                                # subquery into the detected subquery
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   369
                                raise BadSchemaDefinition(
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   370
                                    "cant insert security because of usage two inlined "
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   371
                                    "relations in this query. You should probably at "
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   372
                                    "least uninline %s" % rel.r_type)
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   373
                            subselect.append_selected(vref.copy(subselect))
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   374
                            aliases.append(vref.name)
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   375
                        self.select.remove_node(rel)
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   376
                        # when some inlined relation has to be copied in the
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   377
                        # subquery and that relation is optional, we need to
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   378
                        # test that either value is NULL or that the snippet
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   379
                        # condition is satisfied
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   380
                        if varname == selectvar and rel.optional and rschema.inlined:
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   381
                            need_null_test = True
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   382
                        # also, if some attributes or inlined relation of the
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   383
                        # object variable are accessed, we need to get all those
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   384
                        # from the subquery as well
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   385
                        if vref.name not in done and rschema.inlined:
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   386
                            # we can use vref here define in above for loop
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   387
                            ostinfo = vref.variable.stinfo
7850
d14b77c42b06 [test] sort to avoid random failure due to dict order
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7843
diff changeset
   388
                            for orel in iter_relations(ostinfo):
7843
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   389
                                orschema = get_rschema(orel.r_type)
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   390
                                if orschema.final or orschema.inlined:
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   391
                                    todo.append( (vref.name, ostinfo) )
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   392
                                    break
7139
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   393
            if need_null_test:
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   394
                snippetrqlst = n.Or(
7843
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   395
                    n.make_relation(subselect.get_variable(selectvar), 'is',
3b51806da60b [rqlrewrite] if inlined relation has to be moved to a subquery, take care of the object of the relation (closes #1945725)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7555
diff changeset
   396
                                    (None, None), n.Constant,
7139
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   397
                                    operator='='),
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   398
                    snippetrqlst)
4907
e623afd49356 [rql rewriting] handle case where we've and optional inlined relation in the original query. Also, we should append EXISTS even in subquery to avoid inserting duplicates in results
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4906
diff changeset
   399
        subselect.add_restriction(snippetrqlst)
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
   400
        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
   401
            # 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
   402
            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
   403
            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
   404
                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
   405
            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
   406
                                               '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
   407
            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
   408
        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
   409
                              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
   410
        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
   411
        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
   412
        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
   413
                   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
   414
        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
   415
        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
   416
        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
   417
            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
   418
        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
   419
            # some solutions have been lost, can't apply this rql expr
4318
8a6356914bd0 fix #615848: undefined 'new' variable was refering to the newly introduced subquery / remove_subquery doesn't take an undefine argument (probable copy/paste from the remove_node call)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4212
diff changeset
   420
            self.select.remove_subquery(self.select.with_[-1])
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
   421
            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
   422
        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
   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 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
   425
        # 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
   426
        # "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
   427
        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
   428
        # 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
   429
        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
   430
        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
   431
        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
   432
            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
   433
            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
   434
            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
   435
            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
   436
            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
   437
        # 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
   438
        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
   439
            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
   440
            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
   441
                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
   442
                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
   443
                    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
   444
                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
   445
                    # 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
   446
                    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
   447
                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
   448
                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
   449
        # 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
   450
        #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
   451
        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
   452
        # 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
   453
        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
   454
                                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
   455
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   456
    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
   457
        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
   458
        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
   459
            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
   460
            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
   461
                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
   462
            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
   463
        # 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
   464
        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
   465
        # 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
   466
        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
   467
            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
   468
            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
   469
            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
   470
                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
   471
                    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
   472
            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
   473
                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
   474
                    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
   475
        return variantes
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   476
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   477
    def _cleanup_inserted(self, node):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   478
        # 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
   479
        for vref in node.iget_nodes(n.VariableRef):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   480
            vref.unregister_reference()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   481
            if not vref.variable.stinfo['references']:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   482
                # no more references, undefine the variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   483
                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
   484
7138
9aba650eea6b [rql rewriter] drop unused argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7137
diff changeset
   485
    def _may_be_shared_with(self, sniprel, target):
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
   486
        """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
   487
        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
   488
        """
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
   489
        rschema = self.schema.rschema(sniprel.r_type)
7555
c3bf459268d7 [rqlrewrite] closes #1772135: 1. don't try to reuse a relation from another statement (eg because a subquery has been introduced) 2. _use_orig_term should consider the current statement
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7535
diff changeset
   490
        stmt = self.current_statement()
7139
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   491
        for vi in self.varinfos:
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   492
            try:
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   493
                if target == 'object':
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   494
                    orel = vi['lhs_rels'][sniprel.r_type]
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   495
                    cardindex = 0
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   496
                    ttypes_func = rschema.objects
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   497
                    rdef = rschema.rdef
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   498
                else: # target == 'subject':
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   499
                    orel = vi['rhs_rels'][sniprel.r_type]
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   500
                    cardindex = 1
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   501
                    ttypes_func = rschema.subjects
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   502
                    rdef = lambda x, y: rschema.rdef(y, x)
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   503
            except KeyError:
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   504
                # may be raised by vi['xhs_rels'][sniprel.r_type]
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   505
                return None
7555
c3bf459268d7 [rqlrewrite] closes #1772135: 1. don't try to reuse a relation from another statement (eg because a subquery has been introduced) 2. _use_orig_term should consider the current statement
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7535
diff changeset
   506
            # don't share if relation's statement is not the current statement
c3bf459268d7 [rqlrewrite] closes #1772135: 1. don't try to reuse a relation from another statement (eg because a subquery has been introduced) 2. _use_orig_term should consider the current statement
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7535
diff changeset
   507
            if orel.stmt is not stmt:
c3bf459268d7 [rqlrewrite] closes #1772135: 1. don't try to reuse a relation from another statement (eg because a subquery has been introduced) 2. _use_orig_term should consider the current statement
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7535
diff changeset
   508
                return None
7139
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   509
            # can't share neged relation or relations with different outer join
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   510
            if (orel.neged(strict=True) or sniprel.neged(strict=True)
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   511
                or (orel.optional and orel.optional != sniprel.optional)):
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   512
                return None
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   513
            # if cardinality is in '?1', we can ignore the snippet relation and use
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   514
            # variable from the original query
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   515
            for etype in vi['stinfo']['possibletypes']:
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   516
                for ttype in ttypes_func(etype):
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   517
                    if rdef(etype, ttype).cardinality[cardindex] in '+*':
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   518
                        return None
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   519
            break
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
   520
        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
   521
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
   522
    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
   523
        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
   524
        if key in self.rewritten:
7555
c3bf459268d7 [rqlrewrite] closes #1772135: 1. don't try to reuse a relation from another statement (eg because a subquery has been introduced) 2. _use_orig_term should consider the current statement
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7535
diff changeset
   525
            stmt = self.current_statement()
c3bf459268d7 [rqlrewrite] closes #1772135: 1. don't try to reuse a relation from another statement (eg because a subquery has been introduced) 2. _use_orig_term should consider the current statement
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7535
diff changeset
   526
            insertedvar = stmt.defined_vars.pop(self.rewritten[key])
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
            for inserted_vref in insertedvar.references():
7555
c3bf459268d7 [rqlrewrite] closes #1772135: 1. don't try to reuse a relation from another statement (eg because a subquery has been introduced) 2. _use_orig_term should consider the current statement
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7535
diff changeset
   528
                inserted_vref.parent.replace(inserted_vref, term.copy(stmt))
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
        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
   530
8604a15995d1 refactor so that rql rewriter may be 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
    def _get_varname_or_term(self, vname):
7535
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   532
        stmt = self.current_statement()
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
   533
        if vname == 'U':
7535
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   534
            stmt = self.select
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
   535
            if self.u_varname is None:
7535
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   536
                self.u_varname = stmt.allocate_varname()
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
   537
                # generate an identifier for the substitution
7535
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   538
                argname = stmt.allocate_varname()
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
   539
                while argname in self.kwargs:
7535
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   540
                    argname = stmt.allocate_varname()
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
   541
                # insert "U eid %(u)s"
7535
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   542
                stmt.add_constant_restriction(
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   543
                    stmt.get_variable(self.u_varname),
4721
8f63691ccb7f pylint style fixes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4719
diff changeset
   544
                    'eid', unicode(argname), 'Substitute')
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
   545
                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
   546
            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
   547
        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
   548
        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
   549
            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
   550
        except KeyError:
7535
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   551
            self.rewritten[key] = newvname = stmt.allocate_varname()
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
   552
            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
   553
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   554
    # 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
   555
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   556
    def _visit_binary(self, node, cls):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   557
        newnode = cls()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   558
        for c in node.children:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   559
            new = c.accept(self)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   560
            if new is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   561
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   562
            newnode.append(new)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   563
        if len(newnode.children) == 0:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   564
            return None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   565
        if len(newnode.children) == 1:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   566
            return newnode.children[0]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   567
        return newnode
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   568
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   569
    def _visit_unary(self, node, cls):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   570
        newc = node.children[0].accept(self)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   571
        if newc is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   572
            return None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   573
        newnode = cls()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   574
        newnode.append(newc)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1138
diff changeset
   575
        return newnode
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1138
diff changeset
   576
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
   577
    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
   578
        return self._visit_binary(node, n.And)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   579
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
   580
    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
   581
        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
   582
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   583
    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
   584
        return self._visit_unary(node, n.Not)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   585
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   586
    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
   587
        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
   588
3826
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   589
    def keep_var(self, varname):
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   590
        if varname in 'SO':
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   591
            return varname in self.existingvars
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   592
        if varname == 'U':
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   593
            return True
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   594
        vargraph = self.current_expr.vargraph
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   595
        for existingvar in self.existingvars:
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   596
            #path = has_path(vargraph, varname, existingvar)
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   597
            if has_path(vargraph, varname, existingvar):
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   598
                return True
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   599
        # no path from this variable to an existing variable
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   600
        return False
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   601
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
   602
    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
   603
        lhs, rhs = node.get_variable_parts()
3826
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   604
        # remove relations where an unexistant variable and or a variable linked
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   605
        # to an unexistant variable is used.
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   606
        if self.existingvars:
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   607
            if not self.keep_var(lhs.name):
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   608
                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
   609
        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
   610
                           '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
   611
            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
   612
            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
   613
            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
   614
            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
   615
            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
   616
        if isinstance(rhs, n.VariableRef):
3826
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   617
            if self.existingvars and not self.keep_var(rhs.name):
0c0c051863cb close #511810: bad rql generated when looking for vocabulary for a relation on an entity which doesn't exist (yet)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   618
                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
   619
            if lhs.name in self.revvarmap and rhs.name != 'U':
7138
9aba650eea6b [rql rewriter] drop unused argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7137
diff changeset
   620
                orel = self._may_be_shared_with(node, 'object')
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
   621
                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
   622
                    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
   623
                    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
   624
            elif rhs.name in self.revvarmap and lhs.name != 'U':
7138
9aba650eea6b [rql rewriter] drop unused argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7137
diff changeset
   625
                orel = self._may_be_shared_with(node, 'subject')
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
   626
                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
   627
                    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
   628
                    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
   629
        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
   630
        for c in node.children:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   631
            rel.append(c.accept(self))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   632
        return rel
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   633
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
   634
    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
   635
        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
   636
        for c in node.children:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   637
            cmp_.append(c.accept(self))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   638
        return cmp_
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   639
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
   640
    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
   641
        cmp_ = n.MathExpression(node.operator)
7879
9aae456abab5 [pylint] fix pylint detected errors and tweak it so that pylint -E will be much less verbose next time (+ update some copyrights on the way)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7850
diff changeset
   642
        for c in node.children:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   643
            cmp_.append(c.accept(self))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   644
        return cmp_
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1138
diff changeset
   645
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
   646
    def visit_function(self, node):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   647
        """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
   648
        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
   649
        for c in node.children:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   650
            function_.append(c.accept(self))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   651
        return function_
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   652
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
   653
    def visit_constant(self, node):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   654
        """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
   655
        return n.Constant(node.value, node.type)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   656
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
   657
    def visit_variableref(self, node):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   658
        """get the sql name for a variable reference"""
7535
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   659
        stmt = self.current_statement()
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
   660
        if node.name in self.revvarmap:
7139
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   661
            selectvar, index = self.revvarmap[node.name]
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   662
            vi = self.varinfos[index]
20807d3d7cf6 [rql rewriter] to properly handle 'relation' rql expressions, rql rewriter must support multiple variables (eg S and O) at once to be given as varmap
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7138
diff changeset
   663
            if vi.get('const') is not None:
8056
8909800a8c51 [cleanup] drop some appengine support junk
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7879
diff changeset
   664
                return n.Constant(vi['const'], 'Int')
7535
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   665
            return n.VariableRef(stmt.get_variable(selectvar))
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
   666
        vname_or_term = self._get_varname_or_term(node.name)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   667
        if isinstance(vname_or_term, basestring):
7535
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   668
            return n.VariableRef(stmt.get_variable(vname_or_term))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   669
        # shared term
7535
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   670
        return vname_or_term.copy(stmt)
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   671
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   672
    def current_statement(self):
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   673
        if self._insert_scope is None:
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   674
            return self.select
d5725a89dac9 [rqlrewrite] test and fix rql snippets insertion when several snippets match an optional variable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7251
diff changeset
   675
        return self._insert_scope.stmt