author | Stephanie Marcu <stephanie.marcu@logilab.fr> |
Fri, 22 Oct 2010 14:54:24 +0200 | |
changeset 6592 | 4dad0ec0a44f |
parent 6426 | 541659c39f6a |
child 6889 | 37668bf302f5 |
permissions | -rw-r--r-- |
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
|
1 |
# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
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 | 19 |
|
4869
230ace4d68c0
[write security] we must check perm with read security disabled + add missing eid argument to check_perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4835
diff
changeset
|
20 |
from __future__ import with_statement |
230ace4d68c0
[write security] we must check perm with read security disabled + add missing eid argument to check_perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4835
diff
changeset
|
21 |
|
0 | 22 |
__docformat__ = "restructuredtext en" |
23 |
||
6142
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
24 |
from copy import copy |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
25 |
|
0 | 26 |
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
|
27 |
from rql.nodes import Constant, Relation |
0 | 28 |
|
29 |
from cubicweb import QueryError, typed_eid |
|
2596
d02eed70937f
[R repo, schema] use VIRTUAL_RTYPES const
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2101
diff
changeset
|
30 |
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
|
31 |
from cubicweb.rqlrewrite import add_types_restriction |
4869
230ace4d68c0
[write security] we must check perm with read security disabled + add missing eid argument to check_perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4835
diff
changeset
|
32 |
from cubicweb.server.session import security_enabled |
5067
adc2122eed03
[repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5058
diff
changeset
|
33 |
from cubicweb.server.hook import CleanupDeletedEidsCacheOp |
0 | 34 |
|
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
|
35 |
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
|
36 |
|
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 |
_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
|
38 |
_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
|
39 |
|
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 |
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
|
41 |
"""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
|
42 |
""" |
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 |
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
|
44 |
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
|
45 |
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
|
46 |
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
|
47 |
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
|
48 |
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
|
49 |
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
|
50 |
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
|
51 |
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
|
52 |
# 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
|
53 |
# 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
|
54 |
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
|
55 |
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
|
56 |
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
|
57 |
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
|
58 |
# 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
|
59 |
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
|
60 |
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
|
61 |
attrtype = eschema.subjrels[rtype].objects(eschema)[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
|
62 |
if attrtype == 'Password' and isinstance(value, unicode): |
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 |
value = value.encode('UTF8') |
6142
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
64 |
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
|
65 |
elif to_build.has_key(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
|
66 |
# 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
|
67 |
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
|
68 |
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
|
69 |
to_select.setdefault(edef, []).append( (rtype, rhs, 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
|
70 |
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
|
71 |
|
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 |
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
|
73 |
"""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
|
74 |
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
|
75 |
""" |
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 |
session = plan.session |
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
|
77 |
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
|
78 |
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
|
79 |
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
|
80 |
neweids = session.transaction_data.get('neweids', ()) |
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
|
81 |
checkread = session.read_security |
4869
230ace4d68c0
[write security] we must check perm with read security disabled + add missing eid argument to check_perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4835
diff
changeset
|
82 |
eschema = session.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
|
83 |
for rel in rqlst.where.get_nodes(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
|
84 |
if rel.r_type == 'eid' and not rel.neged(strict=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
|
85 |
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
|
86 |
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
|
87 |
eid = typed_eid(rhs.eval(plan.args)) |
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 |
# 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
|
89 |
# 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
|
90 |
# 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
|
91 |
if checkread and eid not in neweids: |
4869
230ace4d68c0
[write security] we must check perm with read security disabled + add missing eid argument to check_perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4835
diff
changeset
|
92 |
with security_enabled(session, read=False): |
230ace4d68c0
[write security] we must check perm with read security disabled + add missing eid argument to check_perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4835
diff
changeset
|
93 |
eschema(session.describe(eid)[0]).check_perm( |
230ace4d68c0
[write security] we must check perm with read security disabled + add missing eid argument to check_perm
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4835
diff
changeset
|
94 |
session, '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
|
95 |
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
|
96 |
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
|
97 |
|
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
|
98 |
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
|
99 |
"""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
|
100 |
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
|
101 |
|
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 |
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
|
103 |
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
|
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 |
When select has nothing selected, search in origrqlst for restriction 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 |
should be considered. |
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 |
""" |
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
|
108 |
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
|
109 |
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
|
110 |
select.set_where(origrqlst.where.copy(select)) |
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
|
111 |
return select |
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
|
112 |
if origrqlst.where is 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
|
113 |
return |
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
|
114 |
for rel in origrqlst.where.iget_nodes(Relation): |
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
|
115 |
# search for a relation which is neither a type restriction (is) nor an |
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
|
116 |
# eid specification (not neged eid with constant node |
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 rel.neged(strict=True) or not ( |
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 |
rel.is_types_restriction() or |
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 |
(rel.r_type == 'eid' |
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
|
120 |
and isinstance(rel.get_variable_parts()[1], Constant))): |
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
|
121 |
break |
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 |
else: |
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
|
123 |
return |
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
|
124 |
select.set_where(origrqlst.where.copy(select)) |
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
|
125 |
if not 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
|
126 |
# no selection, append one randomly |
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
|
127 |
select.append_selected(rel.children[0].copy(select)) |
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
|
128 |
return select |
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
|
129 |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
130 |
|
6142
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
131 |
_MARKER = object() |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
132 |
|
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
133 |
class dict_protocol_catcher(object): |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
134 |
def __init__(self, entity): |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
135 |
self.__entity = entity |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
136 |
def __getitem__(self, attr): |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
137 |
return self.__entity.cw_edited[attr] |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
138 |
def __setitem__(self, attr, value): |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
139 |
self.__entity.cw_edited[attr] = value |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
140 |
def __getattr__(self, attr): |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
141 |
return getattr(self.__entity, attr) |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
142 |
|
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
143 |
|
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
144 |
class EditedEntity(dict): |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
145 |
"""encapsulate entities attributes being written by an RQL query""" |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
146 |
def __init__(self, entity, **kwargs): |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
147 |
dict.__init__(self, **kwargs) |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
148 |
self.entity = entity |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
149 |
self.skip_security = set() |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
150 |
self.querier_pending_relations = {} |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
151 |
self.saved = False |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
152 |
|
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
153 |
def __hash__(self): |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
154 |
# dict|set keyable |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
155 |
return hash(id(self)) |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
156 |
|
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
157 |
def __cmp__(self, other): |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
158 |
# we don't want comparison by value inherited from dict |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
159 |
return cmp(id(self), id(other)) |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
160 |
|
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
161 |
def __setitem__(self, attr, value): |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
162 |
assert attr != 'eid' |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
163 |
# don't add attribute into skip_security if already in edited |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
164 |
# attributes, else we may accidentaly skip a desired security check |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
165 |
if attr not in self: |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
166 |
self.skip_security.add(attr) |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
167 |
self.edited_attribute(attr, value) |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
168 |
|
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
169 |
def __delitem__(self, attr): |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
170 |
assert not self.saved, 'too late to modify edited attributes' |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
171 |
super(EditedEntity, self).__delitem__(attr) |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
172 |
self.entity.cw_attr_cache.pop(attr, None) |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
173 |
|
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
174 |
def pop(self, attr, *args): |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
175 |
# don't update skip_security by design (think to storage api) |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
176 |
assert not self.saved, 'too late to modify edited attributes' |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
177 |
value = super(EditedEntity, self).pop(attr, *args) |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
178 |
self.entity.cw_attr_cache.pop(attr, *args) |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
179 |
return value |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
180 |
|
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
181 |
def setdefault(self, attr, default): |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
182 |
assert attr != 'eid' |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
183 |
# don't add attribute into skip_security if already in edited |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
184 |
# attributes, else we may accidentaly skip a desired security check |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
185 |
if attr not in self: |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
186 |
self[attr] = default |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
187 |
return self[attr] |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
188 |
|
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
189 |
def update(self, values, skipsec=True): |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
190 |
if skipsec: |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
191 |
setitem = self.__setitem__ |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
192 |
else: |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
193 |
setitem = self.edited_attribute |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
194 |
for attr, value in values.iteritems(): |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
195 |
setitem(attr, value) |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
196 |
|
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
197 |
def edited_attribute(self, attr, value): |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
198 |
"""attribute being edited by a rql query: should'nt be added to |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
199 |
skip_security |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
200 |
""" |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
201 |
assert not self.saved, 'too late to modify edited attributes' |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
202 |
super(EditedEntity, self).__setitem__(attr, value) |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
203 |
self.entity.cw_attr_cache[attr] = value |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
204 |
|
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
205 |
def oldnewvalue(self, attr): |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
206 |
"""returns the couple (old attr value, new attr value) |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
207 |
|
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
208 |
NOTE: will only work in a before_update_entity hook |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
209 |
""" |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
210 |
assert not self.saved, 'too late to get the old value' |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
211 |
# get new value and remove from local dict to force a db query to |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
212 |
# fetch old value |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
213 |
newvalue = self.entity.cw_attr_cache.pop(attr, _MARKER) |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
214 |
oldvalue = getattr(self.entity, attr) |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
215 |
if newvalue is not _MARKER: |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
216 |
self.entity.cw_attr_cache[attr] = newvalue |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
217 |
else: |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
218 |
newvalue = oldvalue |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
219 |
return oldvalue, newvalue |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
220 |
|
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
221 |
def set_defaults(self): |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
222 |
"""set default values according to the schema""" |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
223 |
for attr, value in self.entity.e_schema.defaults(): |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
224 |
if not attr in self: |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
225 |
self[str(attr)] = value |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
226 |
|
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
227 |
def check(self, creation=False): |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
228 |
"""check the entity edition against its schema. Only final relation |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
229 |
are checked here, constraint on actual relations are checked in hooks |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
230 |
""" |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
231 |
entity = self.entity |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
232 |
if creation: |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
233 |
# on creations, we want to check all relations, especially |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
234 |
# required attributes |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
235 |
relations = [rschema for rschema in entity.e_schema.subject_relations() |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
236 |
if rschema.final and rschema.type != 'eid'] |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
237 |
else: |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
238 |
relations = [entity._cw.vreg.schema.rschema(rtype) |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
239 |
for rtype in self] |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
240 |
from yams import ValidationError |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
241 |
try: |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
242 |
entity.e_schema.check(dict_protocol_catcher(entity), |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
243 |
creation=creation, _=entity._cw._, |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
244 |
relations=relations) |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
245 |
except ValidationError, ex: |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
246 |
ex.entity = self.entity |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
247 |
raise |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
248 |
|
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
249 |
def clone(self): |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
250 |
thecopy = EditedEntity(copy(self.entity)) |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
251 |
thecopy.entity.cw_attr_cache = copy(self.entity.cw_attr_cache) |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
252 |
thecopy.entity._cw_related_cache = {} |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
253 |
thecopy.update(self, skipsec=False) |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
254 |
return thecopy |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
255 |
|
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
256 |
|
0 | 257 |
class SSPlanner(object): |
258 |
"""SingleSourcePlanner: build execution plan for rql queries |
|
259 |
||
260 |
optimized for single source repositories |
|
261 |
""" |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
262 |
|
0 | 263 |
def __init__(self, schema, rqlhelper): |
264 |
self.schema = schema |
|
265 |
self.rqlhelper = rqlhelper |
|
266 |
||
267 |
def build_plan(self, plan): |
|
268 |
"""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
|
269 |
|
0 | 270 |
do nothing here, dispatch according to the statement type |
271 |
""" |
|
272 |
build_plan = getattr(self, 'build_%s_plan' % plan.rqlst.TYPE) |
|
273 |
for step in build_plan(plan, plan.rqlst): |
|
274 |
plan.add_step(step) |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
275 |
|
0 | 276 |
def build_select_plan(self, plan, rqlst): |
277 |
"""build execution plan for a SELECT RQL query. Suppose only one source |
|
278 |
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
|
279 |
|
0 | 280 |
the rqlst should not be tagged at this point. |
281 |
""" |
|
282 |
plan.preprocess(rqlst) |
|
283 |
return (OneFetchStep(plan, rqlst, plan.session.repo.sources),) |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
284 |
|
0 | 285 |
def build_insert_plan(self, plan, rqlst): |
286 |
"""get an execution plan from an INSERT RQL query""" |
|
287 |
# each variable in main variables is a new entity to insert |
|
288 |
to_build = {} |
|
289 |
session = plan.session |
|
2650
18aec79ec3a3
R [vreg] important refactoring of the vregistry, moving behaviour to end dictionnary (and so leaving room for more flexibility ; keep bw compat ; update api usage in cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2596
diff
changeset
|
290 |
etype_class = session.vreg['etypes'].etype_class |
0 | 291 |
for etype, var in rqlst.main_variables: |
292 |
# need to do this since entity class is shared w. web client code ! |
|
6142
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
293 |
to_build[var.name] = EditedEntity(etype_class(etype)(session)) |
0 | 294 |
plan.add_entity_def(to_build[var.name]) |
295 |
# 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
|
296 |
to_select = _extract_const_attributes(plan, rqlst, to_build) |
0 | 297 |
# add necessary steps to add relations and update attributes |
298 |
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
|
299 |
step.children += self._compute_relation_steps(plan, rqlst, to_select) |
0 | 300 |
return (step,) |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
301 |
|
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
|
302 |
def _compute_relation_steps(self, plan, rqlst, to_select): |
0 | 303 |
"""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
|
304 |
eidconsts = _extract_eid_consts(plan, rqlst) |
0 | 305 |
for edef, rdefs in to_select.items(): |
306 |
# create a select rql st to fetch needed data |
|
307 |
select = Select() |
|
6142
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
308 |
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
|
309 |
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
|
310 |
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
|
311 |
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
|
312 |
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
|
313 |
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
|
314 |
value = _FROM_SUBSTEP |
0 | 315 |
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
|
316 |
rdefs[i] = (rtype, InsertRelationsStep.REVERSE_RELATION, value) |
0 | 317 |
else: |
3689
deb13e88e037
follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3437
diff
changeset
|
318 |
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
|
319 |
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
|
320 |
rdefs[i] = (rtype, InsertRelationsStep.FINAL, value) |
0 | 321 |
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
|
322 |
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
|
323 |
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
|
324 |
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
|
325 |
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
|
326 |
step.children += self._select_plan(plan, select, rqlst.solutions) |
0 | 327 |
yield step |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
328 |
|
0 | 329 |
def build_delete_plan(self, plan, rqlst): |
330 |
"""get an execution plan from a DELETE RQL query""" |
|
331 |
# build a select query to fetch entities to delete |
|
332 |
steps = [] |
|
333 |
for etype, var in rqlst.main_variables: |
|
334 |
step = DeleteEntitiesStep(plan) |
|
335 |
step.children += self._sel_variable_step(plan, rqlst.solutions, |
|
336 |
rqlst.where, etype, var) |
|
337 |
steps.append(step) |
|
338 |
for relation in rqlst.main_relations: |
|
339 |
step = DeleteRelationsStep(plan, relation.r_type) |
|
340 |
step.children += self._sel_relation_steps(plan, rqlst.solutions, |
|
341 |
rqlst.where, relation) |
|
342 |
steps.append(step) |
|
343 |
return steps |
|
344 |
||
345 |
def _sel_variable_step(self, plan, solutions, restriction, etype, varref): |
|
346 |
"""handle the selection of variables for a delete query""" |
|
347 |
select = Select() |
|
348 |
varref = varref.copy(select) |
|
349 |
select.defined_vars = {varref.name: varref.variable} |
|
350 |
select.append_selected(varref) |
|
351 |
if restriction is not None: |
|
352 |
select.set_where(restriction.copy(select)) |
|
353 |
if etype != 'Any': |
|
354 |
select.add_type_restriction(varref.variable, etype) |
|
355 |
return self._select_plan(plan, select, solutions) |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
356 |
|
0 | 357 |
def _sel_relation_steps(self, plan, solutions, restriction, relation): |
358 |
"""handle the selection of relations for a delete query""" |
|
359 |
select = Select() |
|
360 |
lhs, rhs = relation.get_variable_parts() |
|
361 |
select.append_selected(lhs.copy(select)) |
|
362 |
select.append_selected(rhs.copy(select)) |
|
363 |
select.set_where(relation.copy(select)) |
|
364 |
if restriction is not None: |
|
365 |
select.add_restriction(restriction.copy(select)) |
|
366 |
return self._select_plan(plan, select, solutions) |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
367 |
|
0 | 368 |
def build_set_plan(self, plan, rqlst): |
369 |
"""get an execution plan from an SET RQL query""" |
|
370 |
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
|
371 |
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
|
372 |
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
|
373 |
attributes = set() # edited attributes |
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
|
374 |
updatedefs = [] # definition of update attributes/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
|
375 |
selidx = residx = 0 # substep selection / resulting rset indexes |
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 |
# 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
|
377 |
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
|
378 |
# 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
|
379 |
# 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
|
380 |
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
|
381 |
if relation.r_type in VIRTUAL_RTYPES: |
0 | 382 |
raise QueryError('can not assign to %r relation' |
383 |
% relation.r_type) |
|
384 |
lhs, rhs = relation.get_variable_parts() |
|
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
|
385 |
lhskey = lhs.as_string('utf-8') |
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
|
386 |
if not lhskey in selectedidx: |
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
|
387 |
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
|
388 |
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
|
389 |
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
|
390 |
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
|
391 |
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
|
392 |
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
|
393 |
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
|
394 |
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
|
395 |
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
|
396 |
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
|
397 |
lhsinfo = selectedidx[lhskey][:-1] + (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
|
398 |
rhskey = rhs.as_string('utf-8') |
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
|
399 |
if not rhskey in selectedidx: |
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
|
400 |
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
|
401 |
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
|
402 |
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
|
403 |
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
|
404 |
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
|
405 |
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
|
406 |
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
|
407 |
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
|
408 |
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
|
409 |
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
|
410 |
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
|
411 |
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
|
412 |
rhsinfo = selectedidx[rhskey][:-1] + (None,) |
0 | 413 |
rschema = getrschema(relation.r_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
|
414 |
updatedefs.append( (lhsinfo, rhsinfo, rschema) ) |
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 |
# the update step |
6142
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
416 |
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
|
417 |
# 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
|
418 |
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
|
419 |
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
|
420 |
# 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
|
421 |
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
|
422 |
step.children += self._select_plan(plan, select, rqlst.solutions) |
0 | 423 |
return (step,) |
424 |
||
425 |
# internal methods ######################################################## |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
426 |
|
0 | 427 |
def _select_plan(self, plan, select, solutions): |
428 |
union = Union() |
|
429 |
union.append(select) |
|
430 |
select.clean_solutions(solutions) |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
431 |
add_types_restriction(self.schema, select) |
0 | 432 |
self.rqlhelper.annotate(union) |
433 |
return self.build_select_plan(plan, union) |
|
434 |
||
435 |
||
436 |
# execution steps and helper functions ######################################## |
|
437 |
||
438 |
def varmap_test_repr(varmap, tablesinorder): |
|
439 |
if varmap is None: |
|
440 |
return varmap |
|
441 |
maprepr = {} |
|
442 |
for var, sql in varmap.iteritems(): |
|
443 |
table, col = sql.split('.') |
|
444 |
maprepr[var] = '%s.%s' % (tablesinorder[table], col) |
|
445 |
return maprepr |
|
446 |
||
447 |
def offset_result(offset, result): |
|
448 |
offset -= len(result) |
|
449 |
if offset < 0: |
|
450 |
result = result[offset:] |
|
451 |
offset = None |
|
452 |
elif offset == 0: |
|
453 |
offset = None |
|
454 |
result = () |
|
455 |
return offset, result |
|
456 |
||
457 |
||
458 |
class LimitOffsetMixIn(object): |
|
459 |
limit = offset = None |
|
460 |
def set_limit_offset(self, limit, offset): |
|
461 |
self.limit = limit |
|
462 |
self.offset = offset or None |
|
463 |
||
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
464 |
|
0 | 465 |
class Step(object): |
466 |
"""base abstract class for execution step""" |
|
467 |
def __init__(self, plan): |
|
468 |
self.plan = plan |
|
469 |
self.children = [] |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
470 |
|
0 | 471 |
def execute_child(self): |
472 |
assert len(self.children) == 1 |
|
473 |
return self.children[0].execute() |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
474 |
|
0 | 475 |
def execute_children(self): |
476 |
for step in self.children: |
|
477 |
step.execute() |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
478 |
|
0 | 479 |
def execute(self): |
480 |
"""execute this step and store partial (eg this step) results""" |
|
481 |
raise NotImplementedError() |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
482 |
|
0 | 483 |
def mytest_repr(self): |
484 |
"""return a representation of this step suitable for test""" |
|
485 |
return (self.__class__.__name__,) |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
486 |
|
0 | 487 |
def test_repr(self): |
488 |
"""return a representation of this step suitable for test""" |
|
489 |
return self.mytest_repr() + ( |
|
490 |
[step.test_repr() for step in self.children],) |
|
491 |
||
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
492 |
|
0 | 493 |
class OneFetchStep(LimitOffsetMixIn, Step): |
494 |
"""step consisting in fetching data from sources and directly returning |
|
495 |
results |
|
496 |
""" |
|
497 |
def __init__(self, plan, union, sources, inputmap=None): |
|
498 |
Step.__init__(self, plan) |
|
499 |
self.union = union |
|
500 |
self.sources = sources |
|
501 |
self.inputmap = inputmap |
|
502 |
self.set_limit_offset(union.children[-1].limit, union.children[-1].offset) |
|
503 |
||
504 |
def set_limit_offset(self, limit, offset): |
|
505 |
LimitOffsetMixIn.set_limit_offset(self, limit, offset) |
|
506 |
for select in self.union.children: |
|
507 |
select.limit = limit |
|
508 |
select.offset = offset |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
509 |
|
0 | 510 |
def execute(self): |
511 |
"""call .syntax_tree_search with the given syntax tree on each |
|
512 |
source for each solution |
|
513 |
""" |
|
514 |
self.execute_children() |
|
515 |
session = self.plan.session |
|
516 |
args = self.plan.args |
|
517 |
inputmap = self.inputmap |
|
518 |
union = self.union |
|
519 |
# do we have to use a inputmap from a previous step ? If so disable |
|
520 |
# cachekey |
|
521 |
if inputmap or self.plan.cache_key is None: |
|
522 |
cachekey = None |
|
523 |
# union may have been splited into subqueries, rebuild a cache key |
|
524 |
elif isinstance(self.plan.cache_key, tuple): |
|
525 |
cachekey = list(self.plan.cache_key) |
|
526 |
cachekey[0] = union.as_string() |
|
527 |
cachekey = tuple(cachekey) |
|
528 |
else: |
|
529 |
cachekey = union.as_string() |
|
530 |
result = [] |
|
531 |
# limit / offset processing |
|
532 |
limit = self.limit |
|
533 |
offset = self.offset |
|
534 |
if offset is not None: |
|
535 |
if len(self.sources) > 1: |
|
536 |
# we'll have to deal with limit/offset by ourself |
|
537 |
if union.children[-1].limit: |
|
538 |
union.children[-1].limit = limit + offset |
|
539 |
union.children[-1].offset = None |
|
540 |
else: |
|
541 |
offset, limit = None, None |
|
542 |
for source in self.sources: |
|
543 |
if offset is None and limit is not None: |
|
544 |
# modifying the sample rqlst is enough since sql generation |
|
545 |
# will pick it here as well |
|
546 |
union.children[-1].limit = limit - len(result) |
|
547 |
result_ = source.syntax_tree_search(session, union, args, cachekey, |
|
548 |
inputmap) |
|
549 |
if offset is not None: |
|
550 |
offset, result_ = offset_result(offset, result_) |
|
551 |
result += result_ |
|
552 |
if limit is not None: |
|
553 |
if len(result) >= limit: |
|
554 |
return result[:limit] |
|
555 |
#print 'ONEFETCH RESULT %s' % (result) |
|
556 |
return result |
|
557 |
||
558 |
def mytest_repr(self): |
|
559 |
"""return a representation of this step suitable for test""" |
|
560 |
try: |
|
561 |
inputmap = varmap_test_repr(self.inputmap, self.plan.tablesinorder) |
|
562 |
except AttributeError: |
|
563 |
inputmap = self.inputmap |
|
564 |
return (self.__class__.__name__, |
|
565 |
sorted((r.as_string(kwargs=self.plan.args), r.solutions) |
|
566 |
for r in self.union.children), |
|
567 |
self.limit, self.offset, |
|
568 |
sorted(self.sources), inputmap) |
|
569 |
||
570 |
||
571 |
# UPDATE/INSERT/DELETE steps ################################################## |
|
572 |
||
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
|
573 |
class InsertRelationsStep(Step): |
0 | 574 |
"""step consisting in adding attributes/relations to entity defs from a |
575 |
previous FetchStep |
|
576 |
||
577 |
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
|
578 |
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
|
579 |
|
0 | 580 |
for one entity definition, we'll construct N entity, where N is the |
581 |
number of the latest result |
|
582 |
""" |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
583 |
|
0 | 584 |
FINAL = 0 |
585 |
RELATION = 1 |
|
586 |
REVERSE_RELATION = 2 |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
587 |
|
2921
8e2544e78a5e
test and fix rset returned by SET query
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2875
diff
changeset
|
588 |
def __init__(self, plan, edef, rdefs): |
0 | 589 |
Step.__init__(self, plan) |
590 |
# 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
|
591 |
self.edef = edef |
0 | 592 |
# 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
|
593 |
self.rdefs = rdefs |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
594 |
|
0 | 595 |
def execute(self): |
596 |
"""execute this step""" |
|
2921
8e2544e78a5e
test and fix rset returned by SET query
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2875
diff
changeset
|
597 |
base_edef = self.edef |
8e2544e78a5e
test and fix rset returned by SET query
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2875
diff
changeset
|
598 |
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
|
599 |
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
|
600 |
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
|
601 |
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
|
602 |
result = [[]] |
2921
8e2544e78a5e
test and fix rset returned by SET query
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2875
diff
changeset
|
603 |
for row in result: |
0 | 604 |
# 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
|
605 |
edef = base_edef.clone() |
0 | 606 |
# 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
|
607 |
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
|
608 |
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
|
609 |
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
|
610 |
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
|
611 |
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
|
612 |
if rorder == InsertRelationsStep.FINAL: |
6142
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
613 |
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
|
614 |
elif rorder == InsertRelationsStep.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
|
615 |
self.plan.add_relation_def( (edef, rtype, 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
|
616 |
edef.querier_pending_relations[(rtype, 'subject')] = value |
0 | 617 |
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
|
618 |
self.plan.add_relation_def( (value, rtype, edef) ) |
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
|
619 |
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
|
620 |
edefs.append(edef) |
8e2544e78a5e
test and fix rset returned by SET query
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2875
diff
changeset
|
621 |
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
|
622 |
return result |
0 | 623 |
|
6142
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
624 |
|
0 | 625 |
class InsertStep(Step): |
626 |
"""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
|
627 |
|
0 | 628 |
def execute(self): |
629 |
"""execute this step""" |
|
630 |
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
|
631 |
assert isinstance(step, InsertRelationsStep) |
0 | 632 |
step.plan = self.plan |
633 |
step.execute() |
|
634 |
# insert entities first |
|
635 |
result = self.plan.insert_entity_defs() |
|
636 |
# then relation |
|
637 |
self.plan.insert_relation_defs() |
|
638 |
# return eids of inserted entities |
|
639 |
return result |
|
640 |
||
641 |
||
642 |
class DeleteEntitiesStep(Step): |
|
643 |
"""step consisting in deleting entities""" |
|
644 |
||
645 |
def execute(self): |
|
646 |
"""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
|
647 |
results = self.execute_child() |
5058
6dfeb8e75188
[repo] don't execute child step twice in EntitiesDeleteStep
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4970
diff
changeset
|
648 |
todelete = frozenset(typed_eid(eid) for eid, in results) |
0 | 649 |
session = self.plan.session |
650 |
delete = session.repo.glob_delete_entity |
|
5067
adc2122eed03
[repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5058
diff
changeset
|
651 |
# mark eids as being deleted in session info and setup cache update |
adc2122eed03
[repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5058
diff
changeset
|
652 |
# operation (register pending eids before actual deletion to avoid |
adc2122eed03
[repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5058
diff
changeset
|
653 |
# multiple call to glob_delete_entity) |
6426
541659c39f6a
[hook/operation] nicer api to achieve same result as set_operation, as described in #1253630
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6142
diff
changeset
|
654 |
op = CleanupDeletedEidsCacheOp.get_instance(session) |
541659c39f6a
[hook/operation] nicer api to achieve same result as set_operation, as described in #1253630
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6142
diff
changeset
|
655 |
actual = todelete - op._container |
541659c39f6a
[hook/operation] nicer api to achieve same result as set_operation, as described in #1253630
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6142
diff
changeset
|
656 |
op._container |= actual |
0 | 657 |
for eid in actual: |
658 |
delete(session, eid) |
|
3648
665c37544060
on entity deletion query, return eids of deleted entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3437
diff
changeset
|
659 |
return results |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
660 |
|
0 | 661 |
class DeleteRelationsStep(Step): |
662 |
"""step consisting in deleting relations""" |
|
663 |
||
664 |
def __init__(self, plan, rtype): |
|
665 |
Step.__init__(self, plan) |
|
666 |
self.rtype = rtype |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
667 |
|
0 | 668 |
def execute(self): |
669 |
"""execute this step""" |
|
670 |
session = self.plan.session |
|
671 |
delete = session.repo.glob_delete_relation |
|
672 |
for subj, obj in self.execute_child(): |
|
673 |
delete(session, subj, self.rtype, obj) |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
674 |
|
0 | 675 |
|
676 |
class UpdateStep(Step): |
|
677 |
"""step consisting in updating entities / adding relations from relations |
|
678 |
definitions and from results fetched in previous step |
|
679 |
""" |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
680 |
|
6142
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
681 |
def __init__(self, plan, updatedefs): |
0 | 682 |
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
|
683 |
self.updatedefs = updatedefs |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1016
diff
changeset
|
684 |
|
0 | 685 |
def execute(self): |
686 |
"""execute this step""" |
|
687 |
session = self.plan.session |
|
688 |
repo = session.repo |
|
689 |
edefs = {} |
|
690 |
# 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
|
691 |
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
|
692 |
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
|
693 |
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
|
694 |
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
|
695 |
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
|
696 |
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
|
697 |
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
|
698 |
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
|
699 |
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
|
700 |
if rschema.final or rschema.inlined: |
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
|
701 |
eid = typed_eid(lhsval) |
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
|
702 |
try: |
6142
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
703 |
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
|
704 |
except KeyError: |
6142
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
705 |
edef = session.entity_from_eid(eid) |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
706 |
edefs[eid] = edited = EditedEntity(edef) |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
707 |
edited.edited_attribute(str(rschema), rhsval) |
0 | 708 |
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
|
709 |
repo.glob_add_relation(session, lhsval, str(rschema), rhsval) |
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
|
710 |
result[i] = newrow |
0 | 711 |
# update entities |
6142
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
712 |
for eid, edited in edefs.iteritems(): |
8bc6eac1fac1
[session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5821
diff
changeset
|
713 |
repo.glob_update_entity(session, edited) |
0 | 714 |
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
|
715 |
|
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
|
716 |
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
|
717 |
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
|
718 |
val = 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
|
719 |
else: # _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
|
720 |
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
|
721 |
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
|
722 |
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
|
723 |
return val |