Commit 4593d85f authored by Sylvain Thénault's avatar Sylvain Thénault
Browse files

#759035: Automate addition of eid cachekey in RQL analysis

parent 73760bbb66bd
......@@ -602,7 +602,7 @@ class CubicWebVRegistry(VRegistry):
def solutions(self, req, rqlst, args):
def type_from_eid(eid, req=req):
return req.describe(eid)[0]
self.rqlhelper.compute_solutions(rqlst, {'eid': type_from_eid}, args)
return self.rqlhelper.compute_solutions(rqlst, {'eid': type_from_eid}, args)
def parse(self, req, rql, args=None):
rqlst = self.rqlhelper.parse(rql)
......
......@@ -14,6 +14,7 @@ __docformat__ = "restructuredtext en"
from logging import getLogger
from time import time, clock
from itertools import count
from warnings import warn
from logilab.common.logging_ext import set_log_methods
from logilab.common.decorators import monkeypatch
......@@ -282,9 +283,11 @@ class DBAPIRequest(RequestSessionBase):
if user:
self.set_entity_cache(user)
def execute(self, *args, **kwargs):
"""Session interface compatibility"""
return self.cursor.execute(*args, **kwargs)
def execute(self, rql, args=None, eid_key=None, build_descr=True):
if eid_key is not None:
warn('[3.8] eid_key is deprecated, you can safely remove this argument',
DeprecationWarning, stacklevel=2)
return self.cursor.execute(rql, args, build_descr=build_descr)
set_log_methods(DBAPIRequest, getLogger('cubicweb.dbapi'))
......@@ -706,34 +709,42 @@ class Cursor(object):
self._closed = True
def execute(self, operation, parameters=None, eid_key=None, build_descr=True):
"""Prepare and execute a database operation (query or command).
Parameters may be provided as sequence or mapping and will be bound to
variables in the operation. Variables are specified in a
database-specific notation (see the module's paramstyle attribute for
details).
A reference to the operation will be retained by the cursor. If the
same operation object is passed in again, then the cursor can optimize
its behavior. This is most effective for algorithms where the same
operation is used, but different parameters are bound to it (many
times).
For maximum efficiency when reusing an operation, it is best to use the
setinputsizes() method to specify the parameter types and sizes ahead
of time. It is legal for a parameter to not match the predefined
information; the implementation should compensate, possibly with a loss
of efficiency.
The parameters may also be specified as list of tuples to e.g. insert
multiple rows in a single operation, but this kind of usage is
depreciated: executemany() should be used instead.
Return values are not defined by the DB-API, but this here it returns a
ResultSet object.
def execute(self, rql, args=None, eid_key=None, build_descr=True):
"""execute a rql query, return resulting rows and their description in
a :class:`~cubicweb.rset.ResultSet` object
* `rql` should be an Unicode string or a plain ASCII string, containing
the rql query
* `args` the optional args dictionary associated to the query, with key
matching named substitution in `rql`
* `build_descr` is a boolean flag indicating if the description should
be built on select queries (if false, the description will be en empty
list)
on INSERT queries, there will be one row for each inserted entity,
containing its eid
on SET queries, XXX describe
DELETE queries returns no result.
.. Note::
to maximize the rql parsing/analyzing cache performance, you should
always use substitute arguments in queries, i.e. avoid query such as::
execute('Any X WHERE X eid 123')
use::
execute('Any X WHERE X eid %(x)s', {'x': 123})
"""
self._res = rset = self._repo.execute(self._sessid, operation,
parameters, eid_key, build_descr)
if eid_key is not None:
warn('[3.8] eid_key is deprecated, you can safely remove this argument',
DeprecationWarning, stacklevel=2)
self._res = rset = self._repo.execute(self._sessid, rql,
args, build_descr)
rset.req = self.req
self._index = 0
return rset
......
......@@ -233,8 +233,8 @@ class BaseQuerierTC(TestCase):
self._dumb_sessions.append(s)
return s
def execute(self, rql, args=None, eid_key=None, build_descr=True):
return self.o.execute(self.session, rql, args, eid_key, build_descr)
def execute(self, rql, args=None, build_descr=True):
return self.o.execute(self.session, rql, args, build_descr)
def commit(self):
self.session.commit()
......
......@@ -15,6 +15,7 @@ import re
from urllib import unquote
from math import log
from contextlib import contextmanager
from warnings import warn
import simplejson
......@@ -289,7 +290,7 @@ class CubicWebTC(TestCase):
upassword=password, **kwargs)
req.execute('SET X in_group G WHERE X eid %%(x)s, G name IN(%s)'
% ','.join(repr(g) for g in groups),
{'x': user.eid}, 'x')
{'x': user.eid})
user.clear_related_cache('in_group', 'subject')
if commit:
req.cnx.commit()
......@@ -328,8 +329,11 @@ class CubicWebTC(TestCase):
"""executes <rql>, builds a resultset, and returns a couple (rset, req)
where req is a FakeRequest
"""
if eidkey is not None:
warn('[3.8] eidkey is deprecated, you can safely remove this argument',
DeprecationWarning, stacklevel=2)
req = req or self.request(rql=rql)
return self.cnx.cursor(req).execute(unicode(rql), args, eidkey)
return req.execute(unicode(rql), args)
@nocoverage
def commit(self):
......@@ -350,14 +354,14 @@ class CubicWebTC(TestCase):
# # server side db api #######################################################
def sexecute(self, rql, args=None, eid_key=None):
if eid_key is not None:
warn('[3.8] eid_key is deprecated, you can safely remove this argument',
DeprecationWarning, stacklevel=2)
self.session.set_pool()
return self.session.execute(rql, args, eid_key)
return self.session.execute(rql, args)
# other utilities #########################################################
def entity(self, rql, args=None, eidkey=None, req=None):
return self.execute(rql, args, eidkey, req=req).get_entity(0, 0)
@contextmanager
def temporary_appobjects(self, *appobjects):
self.vreg._loadedmods.setdefault(self.__module__, {})
......@@ -681,29 +685,19 @@ class CubicWebTC(TestCase):
# deprecated ###############################################################
@deprecated('[3.8] use self.execute(...).get_entity(0, 0)')
def entity(self, rql, args=None, eidkey=None, req=None):
if eidkey is not None:
warn('[3.8] eidkey is deprecated, you can safely remove this argument',
DeprecationWarning, stacklevel=2)
return self.execute(rql, args, req=req).get_entity(0, 0)
@deprecated('[3.6] use self.request().create_entity(...)')
def add_entity(self, etype, req=None, **kwargs):
if req is None:
req = self.request()
return req.create_entity(etype, **kwargs)
@deprecated('[3.4] use self.vreg["etypes"].etype_class(etype)(self.request())')
def etype_instance(self, etype, req=None):
req = req or self.request()
e = self.vreg['etypes'].etype_class(etype)(req)
e.eid = None
return e
@nocoverage
@deprecated('[3.4] use req = self.request(); rset = req.execute()',
stacklevel=3)
def rset_and_req(self, rql, optional_args=None, args=None, eidkey=None):
"""executes <rql>, builds a resultset, and returns a
couple (rset, req) where req is a FakeRequest
"""
return (self.execute(rql, args, eidkey),
self.request(rql=rql, **optional_args or {}))
# auto-populating test classes and utilities ###################################
......
......@@ -96,7 +96,7 @@ class CWUser(AnyEntity):
try:
return self._cw.execute(
'Any X WHERE X eid %(x)s, X owned_by U, U eid %(u)s',
{'x': eid, 'u': self.eid}, 'x')
{'x': eid, 'u': self.eid})
except Unauthorized:
return False
owns = cached(owns, keyarg=1)
......@@ -105,13 +105,11 @@ class CWUser(AnyEntity):
rql = 'Any P WHERE P is CWPermission, U eid %(u)s, U in_group G, '\
'P name %(pname)s, P require_group G'
kwargs = {'pname': pname, 'u': self.eid}
cachekey = None
if contexteid is not None:
rql += ', X require_permission P, X eid %(x)s'
kwargs['x'] = contexteid
cachekey = 'x'
try:
return self._cw.execute(rql, kwargs, cachekey)
return self._cw.execute(rql, kwargs)
except Unauthorized:
return False
......
......@@ -23,6 +23,7 @@ def mangle_email(address):
return address
return '%s at %s' % (name, host.replace('.', ' dot '))
class EmailAddress(AnyEntity):
__regid__ = 'EmailAddress'
fetch_attrs, fetch_order = fetch_config(['address', 'alias'])
......@@ -50,8 +51,10 @@ class EmailAddress(AnyEntity):
subjrels = self.e_schema.object_relations()
if not ('sender' in subjrels and 'recipients' in subjrels):
return
rql = 'DISTINCT Any X, S, D ORDERBY D DESC WHERE X sender Y or X recipients Y, X subject S, X date D, Y eid %(y)s'
rset = self._cw.execute(rql, {'y': self.eid}, 'y')
rset = self._cw.execute('DISTINCT Any X, S, D ORDERBY D DESC '
'WHERE X sender Y or X recipients Y, '
'X subject S, X date D, Y eid %(y)s',
{'y': self.eid})
if skipeids is None:
skipeids = set()
for i in xrange(len(rset)):
......@@ -131,7 +134,7 @@ class CWCache(AnyEntity):
def touch(self):
self._cw.execute('SET X timestamp %(t)s WHERE X eid %(x)s',
{'t': datetime.now(), 'x': self.eid}, 'x')
{'t': datetime.now(), 'x': self.eid})
def valid(self, date):
if date:
......
......@@ -69,18 +69,18 @@ class EmailAddressTC(BaseEntityTC):
class CWUserTC(BaseEntityTC):
def test_complete(self):
e = self.entity('CWUser X WHERE X login "admin"')
e = self.execute('CWUser X WHERE X login "admin"').get_entity(0, 0)
e.complete()
def test_matching_groups(self):
e = self.entity('CWUser X WHERE X login "admin"')
e = self.execute('CWUser X WHERE X login "admin"').get_entity(0, 0)
self.failUnless(e.matching_groups('managers'))
self.failIf(e.matching_groups('xyz'))
self.failUnless(e.matching_groups(('xyz', 'managers')))
self.failIf(e.matching_groups(('xyz', 'abcd')))
def test_dc_title_and_name(self):
e = self.entity('CWUser U WHERE U login "member"')
e = self.execute('CWUser U WHERE U login "member"').get_entity(0, 0)
self.assertEquals(e.dc_title(), 'member')
self.assertEquals(e.name(), 'member')
e.set_attributes(firstname=u'bouah')
......@@ -91,7 +91,7 @@ class CWUserTC(BaseEntityTC):
self.assertEquals(e.name(), u'bouah lôt')
def test_allowed_massmail_keys(self):
e = self.entity('CWUser U WHERE U login "member"')
e = self.execute('CWUser U WHERE U login "member"').get_entity(0, 0)
# Bytes/Password attributes should be omited
self.assertEquals(e.allowed_massmail_keys(),
set(('surname', 'firstname', 'login', 'last_login_time',
......
......@@ -96,7 +96,7 @@ class WorkflowTC(CubicWebTC):
self.assertEquals(e.latest_trinfo().comment, 'deactivate 2')
def test_possible_transitions(self):
user = self.entity('CWUser X')
user = self.execute('CWUser X').get_entity(0, 0)
trs = list(user.possible_transitions())
self.assertEquals(len(trs), 1)
self.assertEquals(trs[0].name, u'deactivate')
......@@ -131,7 +131,7 @@ class WorkflowTC(CubicWebTC):
with security_enabled(self.session, write=False):
ex = self.assertRaises(ValidationError, self.session.execute,
'SET X in_state S WHERE X eid %(x)s, S eid %(s)s',
{'x': self.user().eid, 's': s.eid}, 'x')
{'x': self.user().eid, 's': s.eid})
self.assertEquals(ex.errors, {'in_state-subject': "state doesn't belong to entity's workflow. "
"You may want to set a custom workflow for this entity first."})
......@@ -413,7 +413,7 @@ class CustomWorkflowTC(CubicWebTC):
wf = add_wf(self, 'Company')
wf.add_state('asleep', initial=True)
self.execute('SET X custom_workflow WF WHERE X eid %(x)s, WF eid %(wf)s',
{'wf': wf.eid, 'x': self.member.eid}, 'x')
{'wf': wf.eid, 'x': self.member.eid})
ex = self.assertRaises(ValidationError, self.commit)
self.assertEquals(ex.errors, {'custom_workflow-subject': 'workflow isn\'t a workflow for this type'})
......
......@@ -65,7 +65,7 @@ class Workflow(AnyEntity):
def state_by_name(self, statename):
rset = self._cw.execute('Any S, SN WHERE S name SN, S name %(n)s, '
'S state_of WF, WF eid %(wf)s',
{'n': statename, 'wf': self.eid}, 'wf')
{'n': statename, 'wf': self.eid})
if rset:
return rset.get_entity(0, 0)
return None
......@@ -73,7 +73,7 @@ class Workflow(AnyEntity):
def state_by_eid(self, eid):
rset = self._cw.execute('Any S, SN WHERE S name SN, S eid %(s)s, '
'S state_of WF, WF eid %(wf)s',
{'s': eid, 'wf': self.eid}, ('wf', 's'))
{'s': eid, 'wf': self.eid})
if rset:
return rset.get_entity(0, 0)
return None
......@@ -81,7 +81,7 @@ class Workflow(AnyEntity):
def transition_by_name(self, trname):
rset = self._cw.execute('Any T, TN WHERE T name TN, T name %(n)s, '
'T transition_of WF, WF eid %(wf)s',
{'n': trname, 'wf': self.eid}, 'wf')
{'n': trname, 'wf': self.eid})
if rset:
return rset.get_entity(0, 0)
return None
......@@ -89,7 +89,7 @@ class Workflow(AnyEntity):
def transition_by_eid(self, eid):
rset = self._cw.execute('Any T, TN WHERE T name TN, T eid %(t)s, '
'T transition_of WF, WF eid %(wf)s',
{'t': eid, 'wf': self.eid}, ('wf', 't'))
{'t': eid, 'wf': self.eid})
if rset:
return rset.get_entity(0, 0)
return None
......@@ -100,12 +100,12 @@ class Workflow(AnyEntity):
"""add a state to this workflow"""
state = self._cw.create_entity('State', name=unicode(name), **kwargs)
self._cw.execute('SET S state_of WF WHERE S eid %(s)s, WF eid %(wf)s',
{'s': state.eid, 'wf': self.eid}, ('s', 'wf'))
{'s': state.eid, 'wf': self.eid})
if initial:
assert not self.initial, "Initial state already defined as %s" % self.initial
self._cw.execute('SET WF initial_state S '
'WHERE S eid %(s)s, WF eid %(wf)s',
{'s': state.eid, 'wf': self.eid}, ('s', 'wf'))
{'s': state.eid, 'wf': self.eid})
return state
def _add_transition(self, trtype, name, fromstates,
......@@ -113,7 +113,7 @@ class Workflow(AnyEntity):
tr = self._cw.create_entity(trtype, name=unicode(name), **kwargs)
self._cw.execute('SET T transition_of WF '
'WHERE T eid %(t)s, WF eid %(wf)s',
{'t': tr.eid, 'wf': self.eid}, ('t', 'wf'))
{'t': tr.eid, 'wf': self.eid})
assert fromstates, fromstates
if not isinstance(fromstates, (tuple, list)):
fromstates = (fromstates,)
......@@ -122,7 +122,7 @@ class Workflow(AnyEntity):
state = state.eid
self._cw.execute('SET S allowed_transition T '
'WHERE S eid %(s)s, T eid %(t)s',
{'s': state, 't': tr.eid}, ('s', 't'))
{'s': state, 't': tr.eid})
tr.set_permissions(requiredgroups, conditions, reset=False)
return tr
......@@ -136,7 +136,7 @@ class Workflow(AnyEntity):
tostate = tostate.eid
self._cw.execute('SET T destination_state S '
'WHERE S eid %(s)s, T eid %(t)s',
{'t': tr.eid, 's': tostate}, ('s', 't'))
{'t': tr.eid, 's': tostate})
return tr
def add_wftransition(self, name, subworkflow, fromstates, exitpoints=(),
......@@ -147,7 +147,7 @@ class Workflow(AnyEntity):
if hasattr(subworkflow, 'eid'):
subworkflow = subworkflow.eid
assert self._cw.execute('SET T subworkflow WF WHERE WF eid %(wf)s,T eid %(t)s',
{'t': tr.eid, 'wf': subworkflow}, ('wf', 't'))
{'t': tr.eid, 'wf': subworkflow})
for fromstate, tostate in exitpoints:
tr.add_exit_point(fromstate, tostate)
return tr
......@@ -159,11 +159,11 @@ class Workflow(AnyEntity):
if not hasattr(replacement, 'eid'):
replacement = self.state_by_name(replacement)
execute = self._cw.execute
execute('SET X in_state S WHERE S eid %(s)s', {'s': todelstate.eid}, 's')
execute('SET X in_state S WHERE S eid %(s)s', {'s': todelstate.eid})
execute('SET X from_state NS WHERE X to_state OS, OS eid %(os)s, NS eid %(ns)s',
{'os': todelstate.eid, 'ns': replacement.eid}, 's')
{'os': todelstate.eid, 'ns': replacement.eid})
execute('SET X to_state NS WHERE X to_state OS, OS eid %(os)s, NS eid %(ns)s',
{'os': todelstate.eid, 'ns': replacement.eid}, 's')
{'os': todelstate.eid, 'ns': replacement.eid})
todelstate.delete()
......@@ -227,13 +227,13 @@ class BaseTransition(AnyEntity):
"""
if reset:
self._cw.execute('DELETE T require_group G WHERE T eid %(x)s',
{'x': self.eid}, 'x')
{'x': self.eid})
self._cw.execute('DELETE T condition R WHERE T eid %(x)s',
{'x': self.eid}, 'x')
{'x': self.eid})
for gname in requiredgroups:
rset = self._cw.execute('SET T require_group G '
'WHERE T eid %(x)s, G name %(gn)s',
{'x': self.eid, 'gn': gname}, 'x')
{'x': self.eid, 'gn': gname})
assert rset, '%s is not a known group' % gname
if isinstance(conditions, basestring):
conditions = (conditions,)
......@@ -247,7 +247,7 @@ class BaseTransition(AnyEntity):
kwargs.setdefault('mainvars', u'X')
self._cw.execute('INSERT RQLExpression X: X exprtype "ERQLExpression", '
'X expression %(expr)s, X mainvars %(mainvars)s, '
'T condition X WHERE T eid %(x)s',kwargs, 'x')
'T condition X WHERE T eid %(x)s', kwargs)
# XXX clear caches?
@deprecated('[3.6.1] use set_permission')
......@@ -299,15 +299,14 @@ class WorkflowTransition(BaseTransition):
if tostate is None:
self._cw.execute('INSERT SubWorkflowExitPoint X: T subworkflow_exit X, '
'X subworkflow_state FS WHERE T eid %(t)s, FS eid %(fs)s',
{'t': self.eid, 'fs': fromstate}, ('t', 'fs'))
{'t': self.eid, 'fs': fromstate})
else:
if hasattr(tostate, 'eid'):
tostate = tostate.eid
self._cw.execute('INSERT SubWorkflowExitPoint X: T subworkflow_exit X, '
'X subworkflow_state FS, X destination_state TS '
'WHERE T eid %(t)s, FS eid %(fs)s, TS eid %(ts)s',
{'t': self.eid, 'fs': fromstate, 'ts': tostate},
('t', 'fs', 'ts'))
{'t': self.eid, 'fs': fromstate, 'ts': tostate})
def get_exit_point(self, entity, stateeid):
"""if state is an exit point, return its associated destination state"""
......@@ -469,7 +468,7 @@ class WorkflowableMixIn(object):
'T type TT, T type %(type)s, '
'T name TN, T transition_of WF, WF eid %(wfeid)s',
{'x': self.current_state.eid, 'type': type,
'wfeid': self.current_workflow.eid}, 'x')
'wfeid': self.current_workflow.eid})
for tr in rset.entities():
if tr.may_be_fired(self.eid):
yield tr
......
......@@ -500,7 +500,7 @@ class Entity(AppObject, dict):
continue
rql = 'SET X %s V WHERE X eid %%(x)s, Y eid %%(y)s, Y %s V' % (
rschema.type, rschema.type)
execute(rql, {'x': self.eid, 'y': ceid}, ('x', 'y'))
execute(rql, {'x': self.eid, 'y': ceid})
self.clear_related_cache(rschema.type, 'subject')
for rschema in self.e_schema.object_relations():
if rschema.meta:
......@@ -518,7 +518,7 @@ class Entity(AppObject, dict):
continue
rql = 'SET V %s X WHERE X eid %%(x)s, Y eid %%(y)s, V %s Y' % (
rschema.type, rschema.type)
execute(rql, {'x': self.eid, 'y': ceid}, ('x', 'y'))
execute(rql, {'x': self.eid, 'y': ceid})
self.clear_related_cache(rschema.type, 'object')
# data fetching methods ###################################################
......@@ -620,8 +620,7 @@ class Entity(AppObject, dict):
# if some outer join are included to fetch inlined relations
rql = 'Any %s,%s %s' % (V, ','.join(var for attr, var in selected),
','.join(rql))
rset = self._cw.execute(rql, {'x': self.eid}, 'x',
build_descr=False)[0]
rset = self._cw.execute(rql, {'x': self.eid}, build_descr=False)[0]
# handle attributes
for i in xrange(1, lastattr):
self[str(selected[i-1][0])] = rset[i]
......@@ -650,7 +649,7 @@ class Entity(AppObject, dict):
return None
rql = "Any A WHERE X eid %%(x)s, X %s A" % name
try:
rset = self._cw.execute(rql, {'x': self.eid}, 'x')
rset = self._cw.execute(rql, {'x': self.eid})
except Unauthorized:
self[name] = value = None
else:
......@@ -681,7 +680,7 @@ class Entity(AppObject, dict):
pass
assert self.has_eid()
rql = self.related_rql(rtype, role)
rset = self._cw.execute(rql, {'x': self.eid}, 'x')
rset = self._cw.execute(rql, {'x': self.eid})
self.set_related_cache(rtype, role, rset)
return self.related(rtype, role, limit, entities)
......@@ -807,7 +806,7 @@ class Entity(AppObject, dict):
if limit is not None:
before, after = rql.split(' WHERE ', 1)
rql = '%s LIMIT %s WHERE %s' % (before, limit, after)
return self._cw.execute(rql, args, tuple(args))
return self._cw.execute(rql, args)
# relations cache handling ################################################
......@@ -890,7 +889,7 @@ class Entity(AppObject, dict):
# and now update the database
kwargs['x'] = self.eid
self._cw.execute('SET %s WHERE X eid %%(x)s' % ','.join(relations),
kwargs, 'x')
kwargs)
kwargs.pop('x')
# update current local object _after_ the rql query to avoid
# interferences between the query execution itself and the
......@@ -913,13 +912,13 @@ class Entity(AppObject, dict):
restr = 'X %s Y' % attr
if values is None:
self._cw.execute('DELETE %s WHERE X eid %%(x)s' % restr,
{'x': self.eid}, 'x')
{'x': self.eid})
continue
if not isinstance(values, (tuple, list, set, frozenset)):
values = (values,)
self._cw.execute('SET %s WHERE X eid %%(x)s, Y eid IN (%s)' % (
restr, ','.join(str(r.eid) for r in values)),
{'x': self.eid}, 'x')
{'x': self.eid})
def delete(self, **kwargs):
assert self.has_eid(), self.eid
......
......@@ -28,7 +28,7 @@ class SetUseEmailRelationOp(hook.Operation):
if self.condition():
self.session.execute(
'SET X %s Y WHERE X eid %%(x)s, Y eid %%(y)s' % self.rtype,
{'x': self.entity.eid, 'y': self.email.eid}, 'x')
{'x': self.entity.eid, 'y': self.email.eid})
class SetPrimaryEmailRelationOp(SetUseEmailRelationOp):
......
......@@ -77,7 +77,7 @@ class _CheckRequiredRelationOperation(hook.LateOperation):
continue
if rtype in pendingrtypes:
continue
if not session.execute(self.base_rql % rtype, {'x': eid}, 'x'):
if not session.execute(self.base_rql % rtype, {'x': eid}):
etype = session.describe(eid)[0]
_ = session._
msg = _('at least one relation %(rtype)s is required on '
......@@ -304,7 +304,7 @@ class _DelayedDeleteOp(hook.Operation):
# don't do anything if the entity is being created or deleted
if not (eid in pendingeids or eid in neweids):
etype = session.describe(eid)[0]
session.execute(self.base_rql % (etype, rtype), {'x': eid}, 'x')
session.execute(self.base_rql % (etype, rtype), {'x': eid})
class _DelayedDeleteSEntityOp(_DelayedDeleteOp):
"""delete orphan subject entity of a composite relation"""
......
......@@ -102,8 +102,7 @@ class _SyncOwnersOp(hook.Operation):
def precommit_event(self):
self.session.execute('SET X owned_by U WHERE C owned_by U, C eid %(c)s,'
'NOT EXISTS(X owned_by U, X eid %(x)s)',
{'c': self.compositeeid, 'x': self.composedeid},
('c', 'x'))
{'c': self.compositeeid, 'x': self.composedeid})
class SyncCompositeOwner(MetaDataHook):
......
......@@ -124,7 +124,7 @@ class EntityUpdateHook(NotificationHook):
rqlsel.append(var)
rqlrestr.append('X %s %s' % (attr, var))
rql = 'Any %s WHERE %s' % (','.join(rqlsel), ','.join(rqlrestr))
rset = session.execute(rql, {'x': self.entity.eid}, 'x')
rset = session.execute(rql, {'x': self.entity.eid})
for i, attr in enumerate(attrs):
oldvalue = rset[0][i]
newvalue = self.entity[attr]
......
......@@ -1004,7 +1004,7 @@ class AfterDelRelationTypeHook(SyncSchemaHook):
DropRelationTable(session, rschema.type)
# if this is the last instance, drop associated relation type
if lastrel and not self.eidto in pendings:
execute('DELETE CWRType X WHERE X eid %(x)s', {'x': self.eidto}, 'x')
execute('DELETE CWRType X WHERE X eid %(x)s', {'x': self.eidto})
MemSchemaRDefDel(session, (subjschema, rschema, objschema))
......
......@@ -36,7 +36,7 @@ class _GroupOperation(hook.Operation):
no query should be emitted while comitting
"""
rql = 'Any N WHERE G eid %(x)s, G name N'
result = session.execute(rql, {'x': kwargs['geid']}, 'x',</