cubicweb/server/ssplanner.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 03 Nov 2017 12:27:51 +0100
changeset 12227 dc333e9104c9
parent 11767 432f87a63057
child 12242 68ca7fe0ca29
permissions -rw-r--r--
[cleanup] Fix some flake8 errors
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
12227
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
     1
# copyright 2003 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: 5213
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: 5213
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: 5213
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: 5213
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: 5213
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: 5213
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: 5213
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: 5213
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: 5213
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: 5213
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: 5213
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: 5213
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: 5213
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: 5213
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: 5213
diff changeset
    17
# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
5821
656c974961c4 [rql2sql] #1089207: do not encode Unicode strings from RQL statements to db encoding
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5726
diff changeset
    18
"""plan execution of rql queries on a single source"""
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    19
10682
7e111b606005 [py3k] unicode → six.text_type
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
    20
from six import text_type
7e111b606005 [py3k] unicode → six.text_type
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
    21
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    22
from rql.stmts import Union, Select
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    23
from rql.nodes import Constant, Relation
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    24
8748
f5027f8d2478 drop typed_eid() in favour of int() (closes #2742462)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8697
diff changeset
    25
from cubicweb import QueryError
2596
d02eed70937f [R repo, schema] use VIRTUAL_RTYPES const
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2101
diff changeset
    26
from cubicweb.schema import VIRTUAL_RTYPES
3437
a30b5b5138a4 cw.rqlrewrite shouldn't depend on cw.server
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2921
diff changeset
    27
from cubicweb.rqlrewrite import add_types_restriction
7118
e094b3d4eb95 [server] move EditedEntity class to its own module, to avoid cyclic dependency when needed from e.g. session.py
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6893
diff changeset
    28
from cubicweb.server.edition import EditedEntity
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    29
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    30
READ_ONLY_RTYPES = set(('eid', 'has_text', 'is', 'is_instance_of', 'identity'))
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    31
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    32
_CONSTANT = object()
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    33
_FROM_SUBSTEP = object()
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    34
12227
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
    35
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    36
def _extract_const_attributes(plan, rqlst, to_build):
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    37
    """add constant values to entity def, mark variables to be selected
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    38
    """
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    39
    to_select = {}
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    40
    for relation in rqlst.main_relations:
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    41
        lhs, rhs = relation.get_variable_parts()
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    42
        rtype = relation.r_type
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    43
        if rtype in READ_ONLY_RTYPES:
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    44
            raise QueryError("can't assign to %s" % rtype)
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    45
        try:
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    46
            edef = to_build[str(lhs)]
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    47
        except KeyError:
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    48
            # lhs var is not to build, should be selected and added as an
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    49
            # object relation
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    50
            edef = to_build[str(rhs)]
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    51
            to_select.setdefault(edef, []).append((rtype, lhs, 1))
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    52
        else:
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    53
            if isinstance(rhs, Constant) and not rhs.uid:
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    54
                # add constant values to entity def
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    55
                value = rhs.eval(plan.args)
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5821
diff changeset
    56
                eschema = edef.entity.e_schema
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    57
                attrtype = eschema.subjrels[rtype].objects(eschema)[0]
10682
7e111b606005 [py3k] unicode → six.text_type
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
    58
                if attrtype == 'Password' and isinstance(value, text_type):
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    59
                    value = value.encode('UTF8')
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5821
diff changeset
    60
                edef.edited_attribute(rtype, value)
8697
574bb05e40a4 [toward py3k] rewrite has_key() (part of #2711624)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8694
diff changeset
    61
            elif str(rhs) in to_build:
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    62
                # create a relation between two newly created variables
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    63
                plan.add_relation_def((edef, rtype, to_build[rhs.name]))
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    64
            else:
12227
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
    65
                to_select.setdefault(edef, []).append((rtype, rhs, 0))
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    66
    return to_select
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    67
12227
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
    68
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    69
def _extract_eid_consts(plan, rqlst):
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    70
    """return a dict mapping rqlst variable object to their eid if specified in
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    71
    the syntax tree
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    72
    """
9508
1263f1258796 [server] rename session to cnx in querier and plan
Julien Cristau <julien.cristau@logilab.fr>
parents: 9469
diff changeset
    73
    cnx = plan.cnx
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    74
    if rqlst.where is None:
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    75
        return {}
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    76
    eidconsts = {}
9508
1263f1258796 [server] rename session to cnx in querier and plan
Julien Cristau <julien.cristau@logilab.fr>
parents: 9469
diff changeset
    77
    neweids = cnx.transaction_data.get('neweids', ())
1263f1258796 [server] rename session to cnx in querier and plan
Julien Cristau <julien.cristau@logilab.fr>
parents: 9469
diff changeset
    78
    checkread = cnx.read_security
1263f1258796 [server] rename session to cnx in querier and plan
Julien Cristau <julien.cristau@logilab.fr>
parents: 9469
diff changeset
    79
    eschema = cnx.vreg.schema.eschema
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    80
    for rel in rqlst.where.get_nodes(Relation):
8853
f61755c05c89 [querier] fix eid relations handling in SET queries (closes #2797052)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 8127
diff changeset
    81
        # only care for 'eid' relations ...
f61755c05c89 [querier] fix eid relations handling in SET queries (closes #2797052)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 8127
diff changeset
    82
        if (rel.r_type == 'eid'
12227
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
    83
                # ... that are not part of a NOT clause ...
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
    84
                and not rel.neged(strict=True)
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
    85
                # ... and where eid is specified by '=' operator.
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
    86
                and rel.children[1].operator == '='):
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    87
            lhs, rhs = rel.get_variable_parts()
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    88
            if isinstance(rhs, Constant):
8748
f5027f8d2478 drop typed_eid() in favour of int() (closes #2742462)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8697
diff changeset
    89
                eid = int(rhs.eval(plan.args))
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    90
                # check read permission here since it may not be done by
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    91
                # the generated select substep if not emited (eg nothing
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    92
                # to be selected)
4835
13b0b96d7982 [repo] enhanced security handling: deprecates unsafe_execute, in favor of explicit read/write security control using the `enabled_security` context manager. Also code executed on the repository side is now unsafe by default.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4795
diff changeset
    93
                if checkread and eid not in neweids:
9508
1263f1258796 [server] rename session to cnx in querier and plan
Julien Cristau <julien.cristau@logilab.fr>
parents: 9469
diff changeset
    94
                    with cnx.security_enabled(read=False):
11765
9cb215e833b0 [cnx] Use entity_type instead of entity_metas()['type']
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11237
diff changeset
    95
                        eschema(cnx.entity_type(eid)).check_perm(
9508
1263f1258796 [server] rename session to cnx in querier and plan
Julien Cristau <julien.cristau@logilab.fr>
parents: 9469
diff changeset
    96
                            cnx, 'read', eid=eid)
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    97
                eidconsts[lhs.variable] = eid
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    98
    return eidconsts
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    99
12227
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
   100
4795
f1c8bc628b45 [repo] fix bug introduced by 4757:ec9c20c6b9f7, testing for select.selection is not enough to avoid the substep query, we should check there is no interesting restriction (test added)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4764
diff changeset
   101
def _build_substep_query(select, origrqlst):
f1c8bc628b45 [repo] fix bug introduced by 4757:ec9c20c6b9f7, testing for select.selection is not enough to avoid the substep query, we should check there is no interesting restriction (test added)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4764
diff changeset
   102
    """Finalize substep select query that should be executed to get proper
f1c8bc628b45 [repo] fix bug introduced by 4757:ec9c20c6b9f7, testing for select.selection is not enough to avoid the substep query, we should check there is no interesting restriction (test added)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4764
diff changeset
   103
    selection of stuff to insert/update.
f1c8bc628b45 [repo] fix bug introduced by 4757:ec9c20c6b9f7, testing for select.selection is not enough to avoid the substep query, we should check there is no interesting restriction (test added)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4764
diff changeset
   104
f1c8bc628b45 [repo] fix bug introduced by 4757:ec9c20c6b9f7, testing for select.selection is not enough to avoid the substep query, we should check there is no interesting restriction (test added)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4764
diff changeset
   105
    Return None when no query actually needed, else the given select node that
f1c8bc628b45 [repo] fix bug introduced by 4757:ec9c20c6b9f7, testing for select.selection is not enough to avoid the substep query, we should check there is no interesting restriction (test added)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4764
diff changeset
   106
    will be used as substep query.
f1c8bc628b45 [repo] fix bug introduced by 4757:ec9c20c6b9f7, testing for select.selection is not enough to avoid the substep query, we should check there is no interesting restriction (test added)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4764
diff changeset
   107
    """
8018
f01c80513274 [rql] closes #2054468: support for HAVING in SET/DELETE queries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7501
diff changeset
   108
    if origrqlst.where is not None and not select.selection:
f01c80513274 [rql] closes #2054468: support for HAVING in SET/DELETE queries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7501
diff changeset
   109
        # no selection, append one randomly by searching for a relation which is
9206
bf642b50135b [rql / querier] fix bad interpretation of some RQL SET query
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8867
diff changeset
   110
        # not neged neither a type restriction (is/is_instance_of)
8018
f01c80513274 [rql] closes #2054468: support for HAVING in SET/DELETE queries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7501
diff changeset
   111
        for rel in origrqlst.where.iget_nodes(Relation):
9206
bf642b50135b [rql / querier] fix bad interpretation of some RQL SET query
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8867
diff changeset
   112
            if not (rel.neged(traverse_scope=True) or rel.is_types_restriction()):
8018
f01c80513274 [rql] closes #2054468: support for HAVING in SET/DELETE queries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7501
diff changeset
   113
                select.append_selected(rel.children[0].copy(select))
f01c80513274 [rql] closes #2054468: support for HAVING in SET/DELETE queries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7501
diff changeset
   114
                break
f01c80513274 [rql] closes #2054468: support for HAVING in SET/DELETE queries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7501
diff changeset
   115
        else:
9206
bf642b50135b [rql / querier] fix bad interpretation of some RQL SET query
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8867
diff changeset
   116
            return None
4795
f1c8bc628b45 [repo] fix bug introduced by 4757:ec9c20c6b9f7, testing for select.selection is not enough to avoid the substep query, we should check there is no interesting restriction (test added)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4764
diff changeset
   117
    if select.selection:
f1c8bc628b45 [repo] fix bug introduced by 4757:ec9c20c6b9f7, testing for select.selection is not enough to avoid the substep query, we should check there is no interesting restriction (test added)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4764
diff changeset
   118
        if origrqlst.where is not None:
f1c8bc628b45 [repo] fix bug introduced by 4757:ec9c20c6b9f7, testing for select.selection is not enough to avoid the substep query, we should check there is no interesting restriction (test added)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4764
diff changeset
   119
            select.set_where(origrqlst.where.copy(select))
8018
f01c80513274 [rql] closes #2054468: support for HAVING in SET/DELETE queries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7501
diff changeset
   120
        if getattr(origrqlst, 'having', None):
f01c80513274 [rql] closes #2054468: support for HAVING in SET/DELETE queries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7501
diff changeset
   121
            select.set_having([sq.copy(select) for sq in origrqlst.having])
4795
f1c8bc628b45 [repo] fix bug introduced by 4757:ec9c20c6b9f7, testing for select.selection is not enough to avoid the substep query, we should check there is no interesting restriction (test added)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4764
diff changeset
   122
        return select
8018
f01c80513274 [rql] closes #2054468: support for HAVING in SET/DELETE queries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7501
diff changeset
   123
    return None
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   124
12227
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
   125
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   126
class SSPlanner(object):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   127
    """SingleSourcePlanner: build execution plan for rql queries
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   128
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   129
    optimized for single source repositories
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   130
    """
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   131
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   132
    def __init__(self, schema, rqlhelper):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   133
        self.schema = schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   134
        self.rqlhelper = rqlhelper
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   135
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   136
    def build_plan(self, plan):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   137
        """build an execution plan from a RQL query
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   138
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   139
        do nothing here, dispatch according to the statement type
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
        build_plan = getattr(self, 'build_%s_plan' % plan.rqlst.TYPE)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   142
        for step in build_plan(plan, plan.rqlst):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   143
            plan.add_step(step)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   144
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   145
    def build_select_plan(self, plan, rqlst):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   146
        """build execution plan for a SELECT RQL query. Suppose only one source
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   147
        is available and so avoid work need for query decomposition among sources
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   148
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   149
        the rqlst should not be tagged at this point.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   150
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   151
        plan.preprocess(rqlst)
9456
a79e88aad555 [multi-sources-removal] Kill repo.sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9206
diff changeset
   152
        return (OneFetchStep(plan, rqlst),)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   153
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   154
    def build_insert_plan(self, plan, rqlst):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   155
        """get an execution plan from an INSERT RQL query"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   156
        # each variable in main variables is a new entity to insert
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   157
        to_build = {}
9508
1263f1258796 [server] rename session to cnx in querier and plan
Julien Cristau <julien.cristau@logilab.fr>
parents: 9469
diff changeset
   158
        cnx = plan.cnx
1263f1258796 [server] rename session to cnx in querier and plan
Julien Cristau <julien.cristau@logilab.fr>
parents: 9469
diff changeset
   159
        etype_class = cnx.vreg['etypes'].etype_class
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   160
        for etype, var in rqlst.main_variables:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   161
            # need to do this since entity class is shared w. web client code !
9508
1263f1258796 [server] rename session to cnx in querier and plan
Julien Cristau <julien.cristau@logilab.fr>
parents: 9469
diff changeset
   162
            to_build[var.name] = EditedEntity(etype_class(etype)(cnx))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   163
            plan.add_entity_def(to_build[var.name])
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   164
        # add constant values to entity def, mark variables to be selected
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   165
        to_select = _extract_const_attributes(plan, rqlst, to_build)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   166
        # add necessary steps to add relations and update attributes
12227
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
   167
        step = InsertStep(plan)  # insert each entity and its relations
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   168
        step.children += self._compute_relation_steps(plan, rqlst, to_select)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   169
        return (step,)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   170
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   171
    def _compute_relation_steps(self, plan, rqlst, to_select):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   172
        """handle the selection of relations for an insert query"""
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   173
        eidconsts = _extract_eid_consts(plan, rqlst)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   174
        for edef, rdefs in to_select.items():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   175
            # create a select rql st to fetch needed data
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   176
            select = Select()
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5821
diff changeset
   177
            eschema = edef.entity.e_schema
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   178
            for i, (rtype, term, reverse) in enumerate(rdefs):
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   179
                if getattr(term, 'variable', None) in eidconsts:
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   180
                    value = eidconsts[term.variable]
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   181
                else:
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   182
                    select.append_selected(term.copy(select))
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   183
                    value = _FROM_SUBSTEP
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   184
                if reverse:
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   185
                    rdefs[i] = (rtype, InsertRelationsStep.REVERSE_RELATION, value)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   186
                else:
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   187
                    rschema = eschema.subjrels[rtype]
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   188
                    if rschema.final or rschema.inlined:
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   189
                        rdefs[i] = (rtype, InsertRelationsStep.FINAL, value)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   190
                    else:
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   191
                        rdefs[i] = (rtype, InsertRelationsStep.RELATION, value)
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   192
            step = InsertRelationsStep(plan, edef, rdefs)
4795
f1c8bc628b45 [repo] fix bug introduced by 4757:ec9c20c6b9f7, testing for select.selection is not enough to avoid the substep query, we should check there is no interesting restriction (test added)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4764
diff changeset
   193
            select = _build_substep_query(select, rqlst)
f1c8bc628b45 [repo] fix bug introduced by 4757:ec9c20c6b9f7, testing for select.selection is not enough to avoid the substep query, we should check there is no interesting restriction (test added)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4764
diff changeset
   194
            if select is not None:
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   195
                step.children += self._select_plan(plan, select, rqlst.solutions)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   196
            yield step
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   197
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   198
    def build_delete_plan(self, plan, rqlst):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   199
        """get an execution plan from a DELETE RQL query"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   200
        # build a select query to fetch entities to delete
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   201
        steps = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   202
        for etype, var in rqlst.main_variables:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   203
            step = DeleteEntitiesStep(plan)
8018
f01c80513274 [rql] closes #2054468: support for HAVING in SET/DELETE queries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7501
diff changeset
   204
            step.children += self._sel_variable_step(plan, rqlst, etype, var)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   205
            steps.append(step)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   206
        for relation in rqlst.main_relations:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   207
            step = DeleteRelationsStep(plan, relation.r_type)
8018
f01c80513274 [rql] closes #2054468: support for HAVING in SET/DELETE queries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7501
diff changeset
   208
            step.children += self._sel_relation_steps(plan, rqlst, relation)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   209
            steps.append(step)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   210
        return steps
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   211
8018
f01c80513274 [rql] closes #2054468: support for HAVING in SET/DELETE queries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7501
diff changeset
   212
    def _sel_variable_step(self, plan, rqlst, etype, varref):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   213
        """handle the selection of variables for a delete query"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   214
        select = Select()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   215
        varref = varref.copy(select)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   216
        select.defined_vars = {varref.name: varref.variable}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   217
        select.append_selected(varref)
8018
f01c80513274 [rql] closes #2054468: support for HAVING in SET/DELETE queries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7501
diff changeset
   218
        if rqlst.where is not None:
f01c80513274 [rql] closes #2054468: support for HAVING in SET/DELETE queries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7501
diff changeset
   219
            select.set_where(rqlst.where.copy(select))
f01c80513274 [rql] closes #2054468: support for HAVING in SET/DELETE queries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7501
diff changeset
   220
        if getattr(rqlst, 'having', None):
f01c80513274 [rql] closes #2054468: support for HAVING in SET/DELETE queries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7501
diff changeset
   221
            select.set_having([x.copy(select) for x in rqlst.having])
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   222
        if etype != 'Any':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   223
            select.add_type_restriction(varref.variable, etype)
8018
f01c80513274 [rql] closes #2054468: support for HAVING in SET/DELETE queries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7501
diff changeset
   224
        return self._select_plan(plan, select, rqlst.solutions)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   225
8018
f01c80513274 [rql] closes #2054468: support for HAVING in SET/DELETE queries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7501
diff changeset
   226
    def _sel_relation_steps(self, plan, rqlst, relation):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   227
        """handle the selection of relations for a delete query"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   228
        select = Select()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   229
        lhs, rhs = relation.get_variable_parts()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   230
        select.append_selected(lhs.copy(select))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   231
        select.append_selected(rhs.copy(select))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   232
        select.set_where(relation.copy(select))
8018
f01c80513274 [rql] closes #2054468: support for HAVING in SET/DELETE queries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7501
diff changeset
   233
        if rqlst.where is not None:
8020
52e250f307b6 [rql2sql] fix regression introduced in 8018:f01c80513274 leading to bad execution of DELETE queries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8018
diff changeset
   234
            select.add_restriction(rqlst.where.copy(select))
8018
f01c80513274 [rql] closes #2054468: support for HAVING in SET/DELETE queries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7501
diff changeset
   235
        if getattr(rqlst, 'having', None):
f01c80513274 [rql] closes #2054468: support for HAVING in SET/DELETE queries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7501
diff changeset
   236
            select.set_having([x.copy(select) for x in rqlst.having])
f01c80513274 [rql] closes #2054468: support for HAVING in SET/DELETE queries
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7501
diff changeset
   237
        return self._select_plan(plan, select, rqlst.solutions)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   238
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   239
    def build_set_plan(self, plan, rqlst):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   240
        """get an execution plan from an SET RQL query"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   241
        getrschema = self.schema.rschema
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   242
        select = Select()   # potential substep query
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   243
        selectedidx = {}    # local state
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   244
        updatedefs = []     # definition of update attributes/relations
12227
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
   245
        selidx = residx = 0  # substep selection / resulting rset indexes
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   246
        # search for eid const in the WHERE clause
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   247
        eidconsts = _extract_eid_consts(plan, rqlst)
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   248
        # build `updatedefs` describing things to update and add necessary
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   249
        # variables to the substep selection
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   250
        for i, relation in enumerate(rqlst.main_relations):
2596
d02eed70937f [R repo, schema] use VIRTUAL_RTYPES const
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2101
diff changeset
   251
            if relation.r_type in VIRTUAL_RTYPES:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   252
                raise QueryError('can not assign to %r relation'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   253
                                 % relation.r_type)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   254
            lhs, rhs = relation.get_variable_parts()
10314
8f3783dc6358 Don't pass an encoding to rqlst.as_string()
Julien Cristau <julien.cristau@logilab.fr>
parents: 9508
diff changeset
   255
            lhskey = lhs.as_string()
12227
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
   256
            if lhskey not in selectedidx:
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   257
                if lhs.variable in eidconsts:
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   258
                    eid = eidconsts[lhs.variable]
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   259
                    lhsinfo = (_CONSTANT, eid, residx)
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   260
                else:
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   261
                    select.append_selected(lhs.copy(select))
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   262
                    lhsinfo = (_FROM_SUBSTEP, selidx, residx)
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   263
                    selidx += 1
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   264
                residx += 1
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   265
                selectedidx[lhskey] = lhsinfo
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   266
            else:
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   267
                lhsinfo = selectedidx[lhskey][:-1] + (None,)
10314
8f3783dc6358 Don't pass an encoding to rqlst.as_string()
Julien Cristau <julien.cristau@logilab.fr>
parents: 9508
diff changeset
   268
            rhskey = rhs.as_string()
12227
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
   269
            if rhskey not in selectedidx:
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   270
                if isinstance(rhs, Constant):
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   271
                    rhsinfo = (_CONSTANT, rhs.eval(plan.args), residx)
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   272
                elif getattr(rhs, 'variable', None) in eidconsts:
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   273
                    eid = eidconsts[rhs.variable]
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   274
                    rhsinfo = (_CONSTANT, eid, residx)
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   275
                else:
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   276
                    select.append_selected(rhs.copy(select))
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   277
                    rhsinfo = (_FROM_SUBSTEP, selidx, residx)
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   278
                    selidx += 1
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   279
                residx += 1
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   280
                selectedidx[rhskey] = rhsinfo
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   281
            else:
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   282
                rhsinfo = selectedidx[rhskey][:-1] + (None,)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   283
            rschema = getrschema(relation.r_type)
12227
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
   284
            updatedefs.append((lhsinfo, rhsinfo, rschema))
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   285
        # the update step
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5821
diff changeset
   286
        step = UpdateStep(plan, updatedefs)
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   287
        # when necessary add substep to fetch yet unknown values
4795
f1c8bc628b45 [repo] fix bug introduced by 4757:ec9c20c6b9f7, testing for select.selection is not enough to avoid the substep query, we should check there is no interesting restriction (test added)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4764
diff changeset
   288
        select = _build_substep_query(select, rqlst)
f1c8bc628b45 [repo] fix bug introduced by 4757:ec9c20c6b9f7, testing for select.selection is not enough to avoid the substep query, we should check there is no interesting restriction (test added)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4764
diff changeset
   289
        if select is not None:
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   290
            # set distinct to avoid potential duplicate key error
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   291
            select.distinct = True
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   292
            step.children += self._select_plan(plan, select, rqlst.solutions)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   293
        return (step,)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   294
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   295
    # internal methods ########################################################
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   296
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   297
    def _select_plan(self, plan, select, solutions):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   298
        union = Union()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   299
        union.append(select)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   300
        select.clean_solutions(solutions)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   301
        add_types_restriction(self.schema, select)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   302
        self.rqlhelper.annotate(union)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   303
        return self.build_select_plan(plan, union)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   304
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   305
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   306
# execution steps and helper functions ########################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   307
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   308
class Step(object):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   309
    """base abstract class for execution step"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   310
    def __init__(self, plan):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   311
        self.plan = plan
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   312
        self.children = []
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   313
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   314
    def execute_child(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   315
        assert len(self.children) == 1
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   316
        return self.children[0].execute()
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   317
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   318
    def execute_children(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   319
        for step in self.children:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   320
            step.execute()
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   321
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   322
    def execute(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   323
        """execute this step and store partial (eg this step) results"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   324
        raise NotImplementedError()
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   325
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   326
    def mytest_repr(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   327
        """return a representation of this step suitable for test"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   328
        return (self.__class__.__name__,)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   329
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   330
    def test_repr(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   331
        """return a representation of this step suitable for test"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   332
        return self.mytest_repr() + (
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   333
            [step.test_repr() for step in self.children],)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   334
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   335
9456
a79e88aad555 [multi-sources-removal] Kill repo.sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9206
diff changeset
   336
class OneFetchStep(Step):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   337
    """step consisting in fetching data from sources and directly returning
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   338
    results
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   339
    """
11237
f32134dd0067 [repository] drop remanescence of old multi-sources code
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11057
diff changeset
   340
    def __init__(self, plan, union):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   341
        Step.__init__(self, plan)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   342
        self.union = union
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   343
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   344
    def execute(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   345
        """call .syntax_tree_search with the given syntax tree on each
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   346
        source for each solution
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   347
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   348
        self.execute_children()
9508
1263f1258796 [server] rename session to cnx in querier and plan
Julien Cristau <julien.cristau@logilab.fr>
parents: 9469
diff changeset
   349
        cnx = self.plan.cnx
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   350
        args = self.plan.args
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   351
        union = self.union
11237
f32134dd0067 [repository] drop remanescence of old multi-sources code
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11057
diff changeset
   352
        if self.plan.cache_key is None:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   353
            cachekey = None
8127
96d343a5e01b [rql2sql] None for attributes in kwargs generate IS NULL, so should be considered in sql cache key. Closes #2116693
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8020
diff changeset
   354
        # union may have been splited into subqueries, in which case we can't
96d343a5e01b [rql2sql] None for attributes in kwargs generate IS NULL, so should be considered in sql cache key. Closes #2116693
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8020
diff changeset
   355
        # use plan.cache_key, rebuild a cache key
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   356
        elif isinstance(self.plan.cache_key, tuple):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   357
            cachekey = list(self.plan.cache_key)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   358
            cachekey[0] = union.as_string()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   359
            cachekey = tuple(cachekey)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   360
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   361
            cachekey = union.as_string()
9456
a79e88aad555 [multi-sources-removal] Kill repo.sources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9206
diff changeset
   362
        # get results for query
9508
1263f1258796 [server] rename session to cnx in querier and plan
Julien Cristau <julien.cristau@logilab.fr>
parents: 9469
diff changeset
   363
        source = cnx.repo.system_source
11237
f32134dd0067 [repository] drop remanescence of old multi-sources code
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11057
diff changeset
   364
        result = source.syntax_tree_search(cnx, union, args, cachekey)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   365
        return result
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   366
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   367
    def mytest_repr(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   368
        """return a representation of this step suitable for test"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   369
        return (self.__class__.__name__,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   370
                sorted((r.as_string(kwargs=self.plan.args), r.solutions)
11237
f32134dd0067 [repository] drop remanescence of old multi-sources code
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11057
diff changeset
   371
                       for r in self.union.children))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   372
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   373
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   374
# UPDATE/INSERT/DELETE steps ##################################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   375
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   376
class InsertRelationsStep(Step):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   377
    """step consisting in adding attributes/relations to entity defs from a
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   378
    previous FetchStep
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   379
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   380
    relations values comes from the latest result, with one columns for
2921
8e2544e78a5e test and fix rset returned by SET query
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2875
diff changeset
   381
    each relation defined in self.rdefs
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   382
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   383
    for one entity definition, we'll construct N entity, where N is the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   384
    number of the latest result
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   385
    """
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   386
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   387
    FINAL = 0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   388
    RELATION = 1
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   389
    REVERSE_RELATION = 2
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   390
2921
8e2544e78a5e test and fix rset returned by SET query
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2875
diff changeset
   391
    def __init__(self, plan, edef, rdefs):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   392
        Step.__init__(self, plan)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   393
        # partial entity definition to expand
2921
8e2544e78a5e test and fix rset returned by SET query
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2875
diff changeset
   394
        self.edef = edef
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   395
        # definition of relations to complete
2921
8e2544e78a5e test and fix rset returned by SET query
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2875
diff changeset
   396
        self.rdefs = rdefs
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   397
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   398
    def execute(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   399
        """execute this step"""
2921
8e2544e78a5e test and fix rset returned by SET query
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2875
diff changeset
   400
        base_edef = self.edef
8e2544e78a5e test and fix rset returned by SET query
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2875
diff changeset
   401
        edefs = []
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   402
        if self.children:
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   403
            result = self.execute_child()
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   404
        else:
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   405
            result = [[]]
2921
8e2544e78a5e test and fix rset returned by SET query
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2875
diff changeset
   406
        for row in result:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   407
            # get a new entity definition for this row
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5821
diff changeset
   408
            edef = base_edef.clone()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   409
            # complete this entity def using row values
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   410
            index = 0
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   411
            for rtype, rorder, value in self.rdefs:
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   412
                if value is _FROM_SUBSTEP:
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   413
                    value = row[index]
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   414
                    index += 1
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   415
                if rorder == InsertRelationsStep.FINAL:
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5821
diff changeset
   416
                    edef.edited_attribute(rtype, value)
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   417
                elif rorder == InsertRelationsStep.RELATION:
12227
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
   418
                    self.plan.add_relation_def((edef, rtype, value))
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   419
                    edef.querier_pending_relations[(rtype, 'subject')] = value
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   420
                else:
12227
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
   421
                    self.plan.add_relation_def((value, rtype, edef))
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   422
                    edef.querier_pending_relations[(rtype, 'object')] = value
2921
8e2544e78a5e test and fix rset returned by SET query
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2875
diff changeset
   423
            edefs.append(edef)
8e2544e78a5e test and fix rset returned by SET query
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2875
diff changeset
   424
        self.plan.substitute_entity_def(base_edef, edefs)
8e2544e78a5e test and fix rset returned by SET query
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2875
diff changeset
   425
        return result
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   426
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5821
diff changeset
   427
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   428
class InsertStep(Step):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   429
    """step consisting in inserting new entities / relations"""
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   430
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   431
    def execute(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   432
        """execute this step"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   433
        for step in self.children:
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   434
            assert isinstance(step, InsertRelationsStep)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   435
            step.plan = self.plan
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   436
            step.execute()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   437
        # insert entities first
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   438
        result = self.plan.insert_entity_defs()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   439
        # then relation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   440
        self.plan.insert_relation_defs()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   441
        # return eids of inserted entities
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   442
        return result
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   443
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   444
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   445
class DeleteEntitiesStep(Step):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   446
    """step consisting in deleting entities"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   447
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   448
    def execute(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   449
        """execute this step"""
3648
665c37544060 on entity deletion query, return eids of deleted entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   450
        results = self.execute_child()
6893
2e10337c9c2c avoid creating a new instance of CleanupDeletedEidsCacheOp if nothing was deleted
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6889
diff changeset
   451
        if results:
8748
f5027f8d2478 drop typed_eid() in favour of int() (closes #2742462)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8697
diff changeset
   452
            todelete = frozenset(int(eid) for eid, in results)
9508
1263f1258796 [server] rename session to cnx in querier and plan
Julien Cristau <julien.cristau@logilab.fr>
parents: 9469
diff changeset
   453
            cnx = self.plan.cnx
1263f1258796 [server] rename session to cnx in querier and plan
Julien Cristau <julien.cristau@logilab.fr>
parents: 9469
diff changeset
   454
            cnx.repo.glob_delete_entities(cnx, todelete)
3648
665c37544060 on entity deletion query, return eids of deleted entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3437
diff changeset
   455
        return results
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   456
12227
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
   457
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   458
class DeleteRelationsStep(Step):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   459
    """step consisting in deleting relations"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   460
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   461
    def __init__(self, plan, rtype):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   462
        Step.__init__(self, plan)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   463
        self.rtype = rtype
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   464
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   465
    def execute(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   466
        """execute this step"""
9508
1263f1258796 [server] rename session to cnx in querier and plan
Julien Cristau <julien.cristau@logilab.fr>
parents: 9469
diff changeset
   467
        cnx = self.plan.cnx
1263f1258796 [server] rename session to cnx in querier and plan
Julien Cristau <julien.cristau@logilab.fr>
parents: 9469
diff changeset
   468
        delete = cnx.repo.glob_delete_relation
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   469
        for subj, obj in self.execute_child():
9508
1263f1258796 [server] rename session to cnx in querier and plan
Julien Cristau <julien.cristau@logilab.fr>
parents: 9469
diff changeset
   470
            delete(cnx, subj, self.rtype, obj)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   471
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   472
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   473
class UpdateStep(Step):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   474
    """step consisting in updating entities / adding relations from relations
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   475
    definitions and from results fetched in previous step
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   476
    """
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   477
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5821
diff changeset
   478
    def __init__(self, plan, updatedefs):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   479
        Step.__init__(self, plan)
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   480
        self.updatedefs = updatedefs
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1016
diff changeset
   481
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   482
    def execute(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   483
        """execute this step"""
9508
1263f1258796 [server] rename session to cnx in querier and plan
Julien Cristau <julien.cristau@logilab.fr>
parents: 9469
diff changeset
   484
        cnx = self.plan.cnx
1263f1258796 [server] rename session to cnx in querier and plan
Julien Cristau <julien.cristau@logilab.fr>
parents: 9469
diff changeset
   485
        repo = cnx.repo
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   486
        edefs = {}
7237
9f619715665b [server] improve the speed of setting relations between entities (closes #1625257)
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7118
diff changeset
   487
        relations = {}
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   488
        # insert relations
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   489
        if self.children:
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   490
            result = self.execute_child()
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   491
        else:
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   492
            result = [[]]
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   493
        for i, row in enumerate(result):
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   494
            newrow = []
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   495
            for (lhsinfo, rhsinfo, rschema) in self.updatedefs:
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   496
                lhsval = _handle_relterm(lhsinfo, row, newrow)
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   497
                rhsval = _handle_relterm(rhsinfo, row, newrow)
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   498
                if rschema.final or rschema.inlined:
8748
f5027f8d2478 drop typed_eid() in favour of int() (closes #2742462)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8697
diff changeset
   499
                    eid = int(lhsval)
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   500
                    try:
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5821
diff changeset
   501
                        edited = edefs[eid]
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   502
                    except KeyError:
9508
1263f1258796 [server] rename session to cnx in querier and plan
Julien Cristau <julien.cristau@logilab.fr>
parents: 9469
diff changeset
   503
                        edef = cnx.entity_from_eid(eid)
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5821
diff changeset
   504
                        edefs[eid] = edited = EditedEntity(edef)
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5821
diff changeset
   505
                    edited.edited_attribute(str(rschema), rhsval)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   506
                else:
7237
9f619715665b [server] improve the speed of setting relations between entities (closes #1625257)
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7118
diff changeset
   507
                    str_rschema = str(rschema)
9f619715665b [server] improve the speed of setting relations between entities (closes #1625257)
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7118
diff changeset
   508
                    if str_rschema in relations:
9f619715665b [server] improve the speed of setting relations between entities (closes #1625257)
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7118
diff changeset
   509
                        relations[str_rschema].append((lhsval, rhsval))
9f619715665b [server] improve the speed of setting relations between entities (closes #1625257)
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7118
diff changeset
   510
                    else:
9f619715665b [server] improve the speed of setting relations between entities (closes #1625257)
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7118
diff changeset
   511
                        relations[str_rschema] = [(lhsval, rhsval)]
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   512
            result[i] = newrow
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   513
        # update entities
9508
1263f1258796 [server] rename session to cnx in querier and plan
Julien Cristau <julien.cristau@logilab.fr>
parents: 9469
diff changeset
   514
        repo.glob_add_relations(cnx, relations)
10662
10942ed172de [py3k] dict.iteritems → dict.items
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10314
diff changeset
   515
        for eid, edited in edefs.items():
9508
1263f1258796 [server] rename session to cnx in querier and plan
Julien Cristau <julien.cristau@logilab.fr>
parents: 9469
diff changeset
   516
            repo.glob_update_entity(cnx, edited)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   517
        return result
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   518
12227
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
   519
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   520
def _handle_relterm(info, row, newrow):
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   521
    if info[0] is _CONSTANT:
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   522
        val = info[1]
12227
dc333e9104c9 [cleanup] Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11767
diff changeset
   523
    else:  # _FROM_SUBSTEP
4764
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   524
        val = row[info[1]]
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   525
    if info[-1] is not None:
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   526
        newrow.append(val)
ec9c20c6b9f7 [repo] improve planning of insert/update queries: do not select affected constants so the don't go and back to/from the source.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   527
    return val