rqlrewrite.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 23 Sep 2011 14:56:31 +0200
changeset 7848 db6bb2da397c
parent 7843 3b51806da60b
child 7850 d14b77c42b06
permissions -rw-r--r--
backport stable
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)
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    57
    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
    58
        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
    59
        stinfo = var.stinfo
5004
4cc020ee70e2 le patch rql26 a été importé
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4908
diff changeset
    60
        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
    61
            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
    62
        try:
5004
4cc020ee70e2 le patch rql26 a été importé
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4908
diff changeset
    63
            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
    64
        except KeyError:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    65
            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
    66
            continue
5004
4cc020ee70e2 le patch rql26 a été importé
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4908
diff changeset
    67
        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
    68
            mytyperel = typerel
3437
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    69
        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
    70
            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
    71
                rel = vref.relation()
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    72
                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
    73
                    mytyperel = rel
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    74
                    break
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    75
            else:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    76
                mytyperel = None
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    77
        possibletypes = allpossibletypes[varname]
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    78
        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
    79
            # 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
    80
            # 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
    81
            # possible types
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    82
            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
    83
                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
    84
                    cst.parent.remove(cst)
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    85
        else:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    86
            # 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
    87
            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
    88
                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
    89
            else:
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    90
                # 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
    91
                # to the root
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3254
diff changeset
    92
                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
    93
            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
    94
        stinfo['possibletypes'] = possibletypes
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    95
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
    96
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    97
def remove_solutions(origsolutions, solutions, defined):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    98
    """when a rqlst has been generated from another by introducing security
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    99
    assertions, this method returns solutions which are contained in orig
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   100
    solutions
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   101
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   102
    newsolutions = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   103
    for origsol in origsolutions:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   104
        for newsol in solutions[:]:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   105
            for var, etype in origsol.items():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   106
                try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   107
                    if newsol[var] != etype:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   108
                        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   109
                            defined[var].stinfo['possibletypes'].remove(newsol[var])
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   110
                        except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   111
                            pass
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   112
                        break
1132
96752791c2b6 pylint cleanup
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   113
                except KeyError:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   114
                    # variable has been rewritten
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   115
                    continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   116
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   117
                newsolutions.append(newsol)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   118
                solutions.remove(newsol)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   119
    return newsolutions
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   120
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
   121
4721
8f63691ccb7f pylint style fixes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4719
diff changeset
   122
class Unsupported(Exception):
8f63691ccb7f pylint style fixes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4719
diff changeset
   123
    """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
   124
    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
   125
    """
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1138
diff changeset
   126
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
   127
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   128
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
   129
    """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
   130
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   131
    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
   132
    """
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   133
8604a15995d1 refactor so that rql rewriter may be 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
    def __init__(self, session):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   135
        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
   136
        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
   137
        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
   138
        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
   139
        self._compute_solutions = vreg.solutions
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   140
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   141
    def compute_solutions(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   142
        self.annotate(self.select)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   143
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   144
            self._compute_solutions(self.session, self.select, self.kwargs)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   145
        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
   146
            raise Unsupported(str(self.select))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   147
        if len(self.select.solutions) < len(self.solutions):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   148
            raise Unsupported()
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1138
diff changeset
   149
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
   150
    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
   151
        """
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   152
        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
   153
                  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
   154
        """
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
   155
        self.select = select
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   156
        self.solutions = solutions
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   157
        self.kwargs = kwargs
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   158
        self.u_varname = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   159
        self.removing_ambiguity = False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   160
        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
   161
        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
   162
        self.existingvars = existingvars
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   163
        # we have to annotate the rqlst before inserting snippets, even though
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   164
        # we'll have to redo it latter
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   165
        self.annotate(select)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   166
        self.insert_snippets(snippets)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   167
        if not self.exists_snippet and self.u_varname:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   168
            # U has been inserted than cancelled, cleanup
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   169
            select.undefine_variable(select.defined_vars[self.u_varname])
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   170
        # clean solutions according to initial solutions
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   171
        newsolutions = remove_solutions(solutions, select.solutions,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   172
                                        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
   173
        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
   174
            '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
   175
            '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
   176
            '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
   177
            '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
   178
            select, solutions, newsolutions))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   179
        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
   180
            newsolutions = self.remove_ambiguities(snippets, newsolutions)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   181
        select.solutions = newsolutions
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   182
        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
   183
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   184
    def insert_snippets(self, snippets, varexistsmap=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   185
        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
   186
        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
   187
            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
   188
                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
   189
            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
   190
                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
   191
            if varexistsmap is not None and not varmap in varexistsmap:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   192
                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
   193
            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
   194
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
    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
   196
        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
   197
        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
   198
        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
   199
        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
   200
        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
   201
            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
   202
            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
   203
            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
   204
            self.varinfos.append(vi)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   205
            try:
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   206
                vi['const'] = typed_eid(selectvar) # XXX gae
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   207
                vi['rhs_rels'] = vi['lhs_rels'] = {}
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   208
            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
   209
                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
   210
                    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
   211
                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
   212
                    # 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
   213
                    # 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
   214
                    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
   215
                    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
   216
                    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
   217
                    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
   218
                                                      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
   219
                    return
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   220
                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
   221
                    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
   222
                    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
   223
                                           if not r in sti['rhsrelations'])
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   224
                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
   225
                    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
   226
        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
   227
        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
   228
        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
   229
            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
   230
            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
   231
                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
   232
                    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
   233
                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
   234
                    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
   235
                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
   236
                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
   237
                    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
   238
                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
   239
            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
   240
                # 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
   241
                # 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
   242
                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
   243
                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
   244
                    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
   245
        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
   246
            # no rql expression found matching rql solutions. User has no access right
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
            raise Unauthorized() # XXX bad constraint when inserting constraints
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1138
diff changeset
   248
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
   249
    def insert_snippet(self, varmap, snippetrqlst, parent=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   250
        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
   251
        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
   252
        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
   253
        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
   254
            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
   255
        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
   256
            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
   257
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
    def _insert_snippet(self, varmap, parent, new):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   259
        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
   260
            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
   261
                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
   262
                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
   263
                    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
   264
                    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
   265
                        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
   266
                    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
   267
                        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
   268
            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
   269
                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
   270
            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
   271
                                                  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
   272
                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
   273
                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
   274
                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
   275
                #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
   276
                return
7137
01b23ec9c066 [rql rewriter] don't add unnecessary (potentially buggy) exists
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6123
diff changeset
   277
            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
   278
                new = n.Exists(new)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   279
            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
   280
                insert_scope.add_restriction(new)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   281
            else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   282
                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
   283
                or_ = n.Or(parent, new)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   284
                grandpa.replace(parent, or_)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   285
            if not self.removing_ambiguity:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   286
                try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   287
                    self.compute_solutions()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   288
                except Unsupported:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   289
                    # some solutions have been lost, can't apply this rql expr
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   290
                    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
   291
                        self.current_statement().remove_node(new, undefine=True)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   292
                    else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   293
                        parent.parent.replace(or_, or_.children[0])
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   294
                        self._cleanup_inserted(new)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1138
diff changeset
   295
                    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
   296
                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
   297
                    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
   298
                        self.insert_pending()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   299
            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
   300
        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
   301
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   302
    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
   303
        """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
   304
        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
   305
8604a15995d1 refactor so that rql rewriter may be 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
        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
   307
        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
   308
        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
   309
        """
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
   310
        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
   311
        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
   312
            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
   313
            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
   314
                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
   315
            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
   316
                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
   317
                    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
   318
                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
   319
                    # 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
   320
                    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
   321
            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
   322
            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
   323
                # 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
   324
                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
   325
                    '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
   326
                    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
   327
                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
   328
            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
   329
            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
   330
            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
   331
                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
   332
                if not rqlexprs:
3934
d9a29a1fbe43 bugfix typo in exception name
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 3826
diff changeset
   333
                    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
   334
                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
   335
8604a15995d1 refactor so that rql rewriter may be 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
    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
   337
        """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
   338
        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
   339
        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
   340
        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
   341
        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
   342
        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
   343
        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
   344
            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
   345
            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
   346
            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
   347
            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
   348
            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
   349
            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
   350
                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
   351
                done.add(varname)
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
   352
                for rel in stinfo['relations'] - stinfo['rhsrelations']:
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
                    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
   354
                        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
   355
                    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
   356
                    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
   357
                    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
   358
                        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
   359
                        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
   360
                        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
   361
                            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
   362
                                # 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
   363
                                # 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
   364
                                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
   365
                                    "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
   366
                                    "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
   367
                                    "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
   368
                            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
   369
                            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
   370
                        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
   371
                        # 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
   372
                        # 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
   373
                        # 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
   374
                        # 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
   375
                        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
   376
                            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
   377
                        # 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
   378
                        # 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
   379
                        # 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
   380
                        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
   381
                            # 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
   382
                            ostinfo = vref.variable.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
   383
                            for orel in ostinfo['relations'] - ostinfo['rhsrelations']:
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
                                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
   385
                                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
   386
                                    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
   387
                                    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
   388
            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
   389
                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
   390
                    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
   391
                                    (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
   392
                                    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
   393
                    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
   394
        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
   395
        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
   396
            # 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
   397
            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
   398
            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
   399
                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
   400
            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
   401
                                               '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
   402
            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
   403
        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
   404
                              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
   405
        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
   406
        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
   407
        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
   408
                   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
   409
        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
   410
        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
   411
        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
   412
            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
   413
        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
   414
            # 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
   415
            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
   416
            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
   417
        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
   418
8604a15995d1 refactor so that rql rewriter may be 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
    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
   420
        # 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
   421
        # "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
   422
        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
   423
        # 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
   424
        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
   425
        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
   426
        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
   427
            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
   428
            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
   429
            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
   430
            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
   431
            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
   432
        # 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
   433
        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
   434
            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
   435
            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
   436
                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
   437
                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
   438
                    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
   439
                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
   440
                    # 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
   441
                    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
   442
                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
   443
                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
   444
        # 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
   445
        #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
   446
        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
   447
        # 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
   448
        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
   449
                                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
   450
8604a15995d1 refactor so that rql rewriter may be 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
    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
   452
        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
   453
        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
   454
            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
   455
            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
   456
                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
   457
            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
   458
        # 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
   459
        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
   460
        # 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
   461
        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
   462
            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
   463
            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
   464
            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
   465
                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
   466
                    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
   467
            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
   468
                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
   469
                    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
   470
        return variantes
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   471
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   472
    def _cleanup_inserted(self, node):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   473
        # 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
   474
        for vref in node.iget_nodes(n.VariableRef):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   475
            vref.unregister_reference()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   476
            if not vref.variable.stinfo['references']:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   477
                # no more references, undefine the variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   478
                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
   479
7138
9aba650eea6b [rql rewriter] drop unused argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7137
diff changeset
   480
    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
   481
        """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
   482
        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
   483
        """
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
   484
        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
   485
        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
   486
        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
   487
            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
   488
                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
   489
                    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
   490
                    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
   491
                    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
   492
                    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
   493
                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
   494
                    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
   495
                    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
   496
                    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
   497
                    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
   498
            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
   499
                # 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
   500
                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
   501
            # 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
   502
            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
   503
                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
   504
            # 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
   505
            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
   506
                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
   507
                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
   508
            # 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
   509
            # 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
   510
            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
   511
                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
   512
                    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
   513
                        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
   514
            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
   515
        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
   516
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
   517
    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
   518
        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
   519
        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
   520
            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
   521
            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
   522
            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
   523
                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
   524
        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
   525
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   526
    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
   527
        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
   528
        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
   529
            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
   530
            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
   531
                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
   532
                # 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
   533
                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
   534
                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
   535
                    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
   536
                # 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
   537
                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
   538
                    stmt.get_variable(self.u_varname),
4721
8f63691ccb7f pylint style fixes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4719
diff changeset
   539
                    '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
   540
                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
   541
            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
   542
        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
   543
        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
   544
            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
   545
        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
   546
            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
   547
            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
   548
8604a15995d1 refactor so that rql rewriter may be 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
    # 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
   550
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   551
    def _visit_binary(self, node, cls):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   552
        newnode = cls()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   553
        for c in node.children:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   554
            new = c.accept(self)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   555
            if new is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   556
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   557
            newnode.append(new)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   558
        if len(newnode.children) == 0:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   559
            return None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   560
        if len(newnode.children) == 1:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   561
            return newnode.children[0]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   562
        return newnode
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   563
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   564
    def _visit_unary(self, node, cls):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   565
        newc = node.children[0].accept(self)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   566
        if newc is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   567
            return None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   568
        newnode = cls()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   569
        newnode.append(newc)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1138
diff changeset
   570
        return newnode
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1138
diff changeset
   571
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
   572
    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
   573
        return self._visit_binary(node, n.And)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   574
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
   575
    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
   576
        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
   577
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   578
    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
   579
        return self._visit_unary(node, n.Not)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   580
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   581
    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
   582
        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
   583
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
   584
    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
   585
        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
   586
            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
   587
        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
   588
            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
   589
        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
   590
        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
   591
            #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
   592
            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
   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
        # 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
   595
        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
   596
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
   597
    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
   598
        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
   599
        # 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
   600
        # 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
   601
        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
   602
            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
   603
                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
   604
        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
   605
                           '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
   606
            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
   607
            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
   608
            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
   609
            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
   610
            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
   611
        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
   612
            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
   613
                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
   614
            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
   615
                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
   616
                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
   617
                    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
   618
                    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
   619
            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
   620
                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
   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(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
   623
                    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
   624
        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
   625
        for c in node.children:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   626
            rel.append(c.accept(self))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   627
        return rel
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   628
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
    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
   630
        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
   631
        for c in node.children:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   632
            cmp_.append(c.accept(self))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   633
        return cmp_
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   634
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
   635
    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
   636
        cmp_ = n.MathExpression(node.operator)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   637
        for c in cmp.children:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   638
            cmp_.append(c.accept(self))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   639
        return cmp_
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1138
diff changeset
   640
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
   641
    def visit_function(self, node):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   642
        """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
   643
        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
   644
        for c in node.children:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   645
            function_.append(c.accept(self))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   646
        return function_
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   647
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
    def visit_constant(self, node):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   649
        """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
   650
        return n.Constant(node.value, node.type)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   651
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
   652
    def visit_variableref(self, node):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   653
        """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
   654
        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
   655
        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
   656
            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
   657
            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
   658
            if vi.get('const') is not 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
   659
                return n.Constant(vi['const'], 'Int') # XXX gae
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
   660
            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
   661
        vname_or_term = self._get_varname_or_term(node.name)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   662
        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
   663
            return n.VariableRef(stmt.get_variable(vname_or_term))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   664
        # 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
   665
        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
   666
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
   667
    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
   668
        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
   669
            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
   670
        return self._insert_scope.stmt