[server] rename session to cnx in querier and plan
authorJulien Cristau <julien.cristau@logilab.fr>
Wed, 29 Jan 2014 15:29:49 +0100
changeset 9508 1263f1258796
parent 9507 540cb068a7f9
child 9509 592c22e1c5f0
[server] rename session to cnx in querier and plan They don't actually need a session, so let's make that clear.
server/querier.py
server/ssplanner.py
server/test/unittest_querier.py
--- a/server/querier.py	Wed Jan 29 15:55:21 2014 +0100
+++ b/server/querier.py	Wed Jan 29 15:29:49 2014 +0100
@@ -64,16 +64,16 @@
             if etype == 'Password':
                 raise Unauthorized('Password selection is not allowed (%s)' % var)
 
-def term_etype(session, term, solution, args):
+def term_etype(cnx, term, solution, args):
     """return the entity type for the given term (a VariableRef or a Constant
     node)
     """
     try:
         return solution[term.name]
     except AttributeError:
-        return session.entity_metas(term.eval(args))['type']
+        return cnx.entity_metas(term.eval(args))['type']
 
-def check_read_access(session, rqlst, solution, args):
+def check_read_access(cnx, rqlst, solution, args):
     """Check that the given user has credentials to access data read by the
     query and return a dict defining necessary "local checks" (i.e. rql
     expression in read permission defined in the schema) where no group grants
@@ -86,7 +86,7 @@
     # when used as an external source by another repository.
     # XXX what about local read security w/ those rewritten constants...
     DBG = (server.DEBUG & server.DBG_SEC) and 'read' in server._SECURITY_CAPS
-    schema = session.repo.schema
+    schema = cnx.repo.schema
     if rqlst.where is not None:
         for rel in rqlst.where.iget_nodes(Relation):
             # XXX has_text may have specific perm ?
@@ -94,37 +94,37 @@
                 continue
             rschema = schema.rschema(rel.r_type)
             if rschema.final:
-                eschema = schema.eschema(term_etype(session, rel.children[0],
+                eschema = schema.eschema(term_etype(cnx, rel.children[0],
                                                     solution, args))
                 rdef = eschema.rdef(rschema)
             else:
-                rdef = rschema.rdef(term_etype(session, rel.children[0],
+                rdef = rschema.rdef(term_etype(cnx, rel.children[0],
                                                solution, args),
-                                    term_etype(session, rel.children[1].children[0],
+                                    term_etype(cnx, rel.children[1].children[0],
                                                solution, args))
-            if not session.user.matching_groups(rdef.get_groups('read')):
+            if not cnx.user.matching_groups(rdef.get_groups('read')):
                 if DBG:
                     print ('check_read_access: %s %s does not match %s' %
-                           (rdef, session.user.groups, rdef.get_groups('read')))
+                           (rdef, cnx.user.groups, rdef.get_groups('read')))
                 # XXX rqlexpr not allowed
                 raise Unauthorized('read', rel.r_type)
             if DBG:
                 print ('check_read_access: %s %s matches %s' %
-                       (rdef, session.user.groups, rdef.get_groups('read')))
+                       (rdef, cnx.user.groups, rdef.get_groups('read')))
     localchecks = {}
     # iterate on defined_vars and not on solutions to ignore column aliases
     for varname in rqlst.defined_vars:
         eschema = schema.eschema(solution[varname])
         if eschema.final:
             continue
-        if not session.user.matching_groups(eschema.get_groups('read')):
+        if not cnx.user.matching_groups(eschema.get_groups('read')):
             erqlexprs = eschema.get_rqlexprs('read')
             if not erqlexprs:
                 ex = Unauthorized('read', solution[varname])
                 ex.var = varname
                 if DBG:
                     print ('check_read_access: %s %s %s %s' %
-                           (varname, eschema, session.user.groups, eschema.get_groups('read')))
+                           (varname, eschema, cnx.user.groups, eschema.get_groups('read')))
                 raise ex
             # don't insert security on variable only referenced by 'NOT X relation Y' or
             # 'NOT EXISTS(X relation Y)'
@@ -144,21 +144,21 @@
 class ExecutionPlan(object):
     """the execution model of a rql query, composed of querier steps"""
 
-    def __init__(self, querier, rqlst, args, session):
+    def __init__(self, querier, rqlst, args, cnx):
         # original rql syntax tree
         self.rqlst = rqlst
         self.args = args or {}
-        # session executing the query
-        self.session = session
+        # cnx executing the query
+        self.cnx = cnx
         # quick reference to the system source
-        self.syssource = session.repo.system_source
+        self.syssource = cnx.repo.system_source
         # execution steps
         self.steps = []
         # various resource accesors
         self.querier = querier
         self.schema = querier.schema
         self.sqlannotate = querier.sqlgen_annotate
-        self.rqlhelper = session.vreg.rqlhelper
+        self.rqlhelper = cnx.vreg.rqlhelper
 
     def annotate_rqlst(self):
         if not self.rqlst.annotated:
@@ -169,7 +169,7 @@
         self.steps.append(step)
 
     def sqlexec(self, sql, args=None):
-        return self.syssource.sqlexec(self.session, sql, args)
+        return self.syssource.sqlexec(self.cnx, sql, args)
 
     def execute(self):
         """execute a plan and return resulting rows"""
@@ -184,15 +184,15 @@
         return rqlst to actually execute
         """
         cached = None
-        if security and self.session.read_security:
+        if security and self.cnx.read_security:
             # ensure security is turned of when security is inserted,
             # else we may loop for ever...
-            if self.session.transaction_data.get('security-rqlst-cache'):
+            if self.cnx.transaction_data.get('security-rqlst-cache'):
                 key = self.cache_key
             else:
                 key = None
-            if key is not None and key in self.session.transaction_data:
-                cachedunion, args = self.session.transaction_data[key]
+            if key is not None and key in self.cnx.transaction_data:
+                cachedunion, args = self.cnx.transaction_data[key]
                 union.children[:] = []
                 for select in cachedunion.children:
                     union.append(select)
@@ -201,10 +201,10 @@
                 self.args = args
                 cached = True
             else:
-                with self.session.security_enabled(read=False):
+                with self.cnx.security_enabled(read=False):
                     noinvariant = self._insert_security(union)
                 if key is not None:
-                    self.session.transaction_data[key] = (union, self.args)
+                    self.cnx.transaction_data[key] = (union, self.args)
         else:
             noinvariant = ()
         if cached is None:
@@ -221,7 +221,7 @@
                 self._insert_security(subquery.query)
             localchecks, restricted = self._check_permissions(select)
             if any(localchecks):
-                self.session.rql_rewriter.insert_local_checks(
+                self.cnx.rql_rewriter.insert_local_checks(
                     select, self.args, localchecks, restricted, noinvariant)
         return noinvariant
 
@@ -243,12 +243,12 @@
 
         Note rqlst should not have been simplified at this point.
         """
-        session = self.session
+        cnx = self.cnx
         msgs = []
         # dict(varname: eid), allowing to check rql expression for variables
         # which have a known eid
         varkwargs = {}
-        if not session.transaction_data.get('security-rqlst-cache'):
+        if not cnx.transaction_data.get('security-rqlst-cache'):
             for var in rqlst.defined_vars.itervalues():
                 if var.stinfo['constnode'] is not None:
                     eid = var.stinfo['constnode'].eval(self.args)
@@ -259,10 +259,10 @@
         newsolutions = []
         for solution in rqlst.solutions:
             try:
-                localcheck = check_read_access(session, rqlst, solution, self.args)
+                localcheck = check_read_access(cnx, rqlst, solution, self.args)
             except Unauthorized as ex:
                 msg = 'remove %s from solutions since %s has no %s access to %s'
-                msg %= (solution, session.user.login, ex.args[0], ex.args[1])
+                msg %= (solution, cnx.user.login, ex.args[0], ex.args[1])
                 msgs.append(msg)
                 LOGGER.info(msg)
             else:
@@ -277,10 +277,10 @@
                     # if entity has been added in the current transaction, the
                     # user can read it whatever rql expressions are associated
                     # to its type
-                    if session.added_in_transaction(eid):
+                    if cnx.added_in_transaction(eid):
                         continue
                     for rqlexpr in rqlexprs:
-                        if rqlexpr.check(session, eid):
+                        if rqlexpr.check(cnx, eid):
                             break
                     else:
                         raise Unauthorized('No read acces on %r with eid %i.' % (var, eid))
@@ -316,8 +316,8 @@
     """an execution model specific to the INSERT rql query
     """
 
-    def __init__(self, querier, rqlst, args, session):
-        ExecutionPlan.__init__(self, querier, rqlst, args, session)
+    def __init__(self, querier, rqlst, args, cnx):
+        ExecutionPlan.__init__(self, querier, rqlst, args, cnx)
         # save originaly selected variable, we may modify this
         # dictionary for substitution (query parameters)
         self.selected = rqlst.selection
@@ -415,17 +415,17 @@
         if there is two entities matching U, the result set will look like
         [(eidX1, eidY1), (eidX2, eidY2)]
         """
-        session = self.session
-        repo = session.repo
+        cnx = self.cnx
+        repo = cnx.repo
         results = []
         for row in self.e_defs:
-            results.append([repo.glob_add_entity(session, edef)
+            results.append([repo.glob_add_entity(cnx, edef)
                             for edef in row])
         return results
 
     def insert_relation_defs(self):
-        session = self.session
-        repo = session.repo
+        cnx = self.cnx
+        repo = cnx.repo
         edited_entities = {}
         relations = {}
         for subj, rtype, obj in self.relation_defs():
@@ -440,7 +440,7 @@
                 obj = obj.entity.eid
             if repo.schema.rschema(rtype).inlined:
                 if subj not in edited_entities:
-                    entity = session.entity_from_eid(subj)
+                    entity = cnx.entity_from_eid(subj)
                     edited = EditedEntity(entity)
                     edited_entities[subj] = edited
                 else:
@@ -451,9 +451,9 @@
                     relations[rtype].append((subj, obj))
                 else:
                     relations[rtype] = [(subj, obj)]
-        repo.glob_add_relations(session, relations)
+        repo.glob_add_relations(cnx, relations)
         for edited in edited_entities.itervalues():
-            repo.glob_update_entity(session, edited)
+            repo.glob_update_entity(cnx, edited)
 
 
 class QuerierHelper(object):
@@ -495,13 +495,13 @@
         except UnicodeError:
             raise RQLSyntaxError(rql)
 
-    def plan_factory(self, rqlst, args, session):
+    def plan_factory(self, rqlst, args, cnx):
         """create an execution plan for an INSERT RQL query"""
         if rqlst.TYPE == 'insert':
-            return InsertPlan(self, rqlst, args, session)
-        return ExecutionPlan(self, rqlst, args, session)
+            return InsertPlan(self, rqlst, args, cnx)
+        return ExecutionPlan(self, rqlst, args, cnx)
 
-    def execute(self, session, rql, args=None, build_descr=True):
+    def execute(self, cnx, rql, args=None, build_descr=True):
         """execute a rql query, return resulting rows and their description in
         a `ResultSet` object
 
@@ -535,7 +535,7 @@
                     # if there are some, we need a better cache key, eg (rql +
                     # entity type of each eid)
                     try:
-                        cachekey = self._repo.querier_cache_key(session, rql,
+                        cachekey = self._repo.querier_cache_key(cnx, rql,
                                                                 args, eidkeys)
                     except UnknownEid:
                         # we want queries such as "Any X WHERE X eid 9999"
@@ -551,7 +551,7 @@
                 # which are eids. Notice that if you may not need `eidkeys`, we
                 # have to compute solutions anyway (kept as annotation on the
                 # tree)
-                eidkeys = self.solutions(session, rqlst, args)
+                eidkeys = self.solutions(cnx, rqlst, args)
             except UnknownEid:
                 # we want queries such as "Any X WHERE X eid 9999" return an
                 # empty result instead of raising UnknownEid
@@ -559,19 +559,19 @@
             if args and rql not in self._rql_ck_cache:
                 self._rql_ck_cache[rql] = eidkeys
                 if eidkeys:
-                    cachekey = self._repo.querier_cache_key(session, rql, args,
+                    cachekey = self._repo.querier_cache_key(cnx, rql, args,
                                                             eidkeys)
             self._rql_cache[cachekey] = rqlst
         orig_rqlst = rqlst
         if rqlst.TYPE != 'select':
-            if session.read_security:
+            if cnx.read_security:
                 check_no_password_selected(rqlst)
-            # write query, ensure session's mode is 'write' so connections won't
-            # be released until commit/rollback
-            session.mode = 'write'
+            # write query, ensure connection's mode is 'write' so connections
+            # won't be released until commit/rollback
+            cnx.mode = 'write'
             cachekey = None
         else:
-            if session.read_security:
+            if cnx.read_security:
                 for select in rqlst.children:
                     check_no_password_selected(select)
             # on select query, always copy the cached rqlst so we don't have to
@@ -585,7 +585,7 @@
                 cachekey += tuple(sorted([k for k, v in args.iteritems()
                                           if v is None]))
         # make an execution plan
-        plan = self.plan_factory(rqlst, args, session)
+        plan = self.plan_factory(rqlst, args, cnx)
         plan.cache_key = cachekey
         self._planner.build_plan(plan)
         # execute the plan
@@ -597,11 +597,11 @@
             #
             # notes:
             # * we should not reset the connections set here, since we don't want the
-            #   session to loose it during processing
+            #   connection to loose it during processing
             # * don't rollback if we're in the commit process, will be handled
-            #   by the session
-            if session.commit_state is None:
-                session.commit_state = 'uncommitable'
+            #   by the connection
+            if cnx.commit_state is None:
+                cnx.commit_state = 'uncommitable'
             raise
         # build a description for the results if necessary
         descr = ()
@@ -616,14 +616,14 @@
                     descr = RepeatList(len(results), tuple(description))
                 else:
                     # hard, delegate the work :o)
-                    descr = manual_build_descr(session, rqlst, args, results)
+                    descr = manual_build_descr(cnx, rqlst, args, results)
             elif rqlst.TYPE == 'insert':
                 # on insert plan, some entities may have been auto-casted,
                 # so compute description manually even if there is only
                 # one solution
                 basedescr = [None] * len(plan.selected)
                 todetermine = zip(xrange(len(plan.selected)), repeat(False))
-                descr = _build_descr(session, results, basedescr, todetermine)
+                descr = _build_descr(cnx, results, basedescr, todetermine)
             # FIXME: get number of affected entities / relations on non
             # selection queries ?
         # return a result set object
@@ -639,7 +639,7 @@
 set_log_methods(QuerierHelper, LOGGER)
 
 
-def manual_build_descr(tx, rqlst, args, result):
+def manual_build_descr(cnx, rqlst, args, result):
     """build a description for a given result by analysing each row
 
     XXX could probably be done more efficiently during execution of query
@@ -663,11 +663,11 @@
             basedescr.append(ttype)
     if not todetermine:
         return RepeatList(len(result), tuple(basedescr))
-    return _build_descr(tx, result, basedescr, todetermine)
+    return _build_descr(cnx, result, basedescr, todetermine)
 
-def _build_descr(tx, result, basedescription, todetermine):
+def _build_descr(cnx, result, basedescription, todetermine):
     description = []
-    entity_metas = tx.entity_metas
+    entity_metas = cnx.entity_metas
     todel = []
     for i, row in enumerate(result):
         row_descr = basedescription[:]
@@ -683,7 +683,7 @@
                 try:
                     row_descr[index] = entity_metas(value)['type']
                 except UnknownEid:
-                    tx.error('wrong eid %s in repository, you should '
+                    cnx.error('wrong eid %s in repository, you should '
                              'db-check the database' % value)
                     todel.append(i)
                     break
--- a/server/ssplanner.py	Wed Jan 29 15:55:21 2014 +0100
+++ b/server/ssplanner.py	Wed Jan 29 15:29:49 2014 +0100
@@ -68,13 +68,13 @@
     """return a dict mapping rqlst variable object to their eid if specified in
     the syntax tree
     """
-    session = plan.session
+    cnx = plan.cnx
     if rqlst.where is None:
         return {}
     eidconsts = {}
-    neweids = session.transaction_data.get('neweids', ())
-    checkread = session.read_security
-    eschema = session.vreg.schema.eschema
+    neweids = cnx.transaction_data.get('neweids', ())
+    checkread = cnx.read_security
+    eschema = cnx.vreg.schema.eschema
     for rel in rqlst.where.get_nodes(Relation):
         # only care for 'eid' relations ...
         if (rel.r_type == 'eid'
@@ -89,9 +89,9 @@
                 # the generated select substep if not emited (eg nothing
                 # to be selected)
                 if checkread and eid not in neweids:
-                    with session.security_enabled(read=False):
-                        eschema(session.entity_metas(eid)['type']).check_perm(
-                            session, 'read', eid=eid)
+                    with cnx.security_enabled(read=False):
+                        eschema(cnx.entity_metas(eid)['type']).check_perm(
+                            cnx, 'read', eid=eid)
                 eidconsts[lhs.variable] = eid
     return eidconsts
 
@@ -151,11 +151,11 @@
         """get an execution plan from an INSERT RQL query"""
         # each variable in main variables is a new entity to insert
         to_build = {}
-        session = plan.session
-        etype_class = session.vreg['etypes'].etype_class
+        cnx = plan.cnx
+        etype_class = cnx.vreg['etypes'].etype_class
         for etype, var in rqlst.main_variables:
             # need to do this since entity class is shared w. web client code !
-            to_build[var.name] = EditedEntity(etype_class(etype)(session))
+            to_build[var.name] = EditedEntity(etype_class(etype)(cnx))
             plan.add_entity_def(to_build[var.name])
         # add constant values to entity def, mark variables to be selected
         to_select = _extract_const_attributes(plan, rqlst, to_build)
@@ -353,7 +353,7 @@
         source for each solution
         """
         self.execute_children()
-        session = self.plan.session
+        cnx = self.plan.cnx
         args = self.plan.args
         inputmap = self.inputmap
         union = self.union
@@ -370,8 +370,8 @@
         else:
             cachekey = union.as_string()
         # get results for query
-        source = session.repo.system_source
-        result = source.syntax_tree_search(session, union, args, cachekey, inputmap)
+        source = cnx.repo.system_source
+        result = source.syntax_tree_search(cnx, union, args, cachekey, inputmap)
         #print 'ONEFETCH RESULT %s' % (result)
         return result
 
@@ -466,8 +466,8 @@
         results = self.execute_child()
         if results:
             todelete = frozenset(int(eid) for eid, in results)
-            session = self.plan.session
-            session.repo.glob_delete_entities(session, todelete)
+            cnx = self.plan.cnx
+            cnx.repo.glob_delete_entities(cnx, todelete)
         return results
 
 class DeleteRelationsStep(Step):
@@ -479,10 +479,10 @@
 
     def execute(self):
         """execute this step"""
-        session = self.plan.session
-        delete = session.repo.glob_delete_relation
+        cnx = self.plan.cnx
+        delete = cnx.repo.glob_delete_relation
         for subj, obj in self.execute_child():
-            delete(session, subj, self.rtype, obj)
+            delete(cnx, subj, self.rtype, obj)
 
 
 class UpdateStep(Step):
@@ -496,8 +496,8 @@
 
     def execute(self):
         """execute this step"""
-        session = self.plan.session
-        repo = session.repo
+        cnx = self.plan.cnx
+        repo = cnx.repo
         edefs = {}
         relations = {}
         # insert relations
@@ -515,7 +515,7 @@
                     try:
                         edited = edefs[eid]
                     except KeyError:
-                        edef = session.entity_from_eid(eid)
+                        edef = cnx.entity_from_eid(eid)
                         edefs[eid] = edited = EditedEntity(edef)
                     edited.edited_attribute(str(rschema), rhsval)
                 else:
@@ -526,9 +526,9 @@
                         relations[str_rschema] = [(lhsval, rhsval)]
             result[i] = newrow
         # update entities
-        repo.glob_add_relations(session, relations)
+        repo.glob_add_relations(cnx, relations)
         for eid, edited in edefs.iteritems():
-            repo.glob_update_entity(session, edited)
+            repo.glob_update_entity(cnx, edited)
         return result
 
 def _handle_relterm(info, row, newrow):
--- a/server/test/unittest_querier.py	Wed Jan 29 15:55:21 2014 +0100
+++ b/server/test/unittest_querier.py	Wed Jan 29 15:29:49 2014 +0100
@@ -127,7 +127,7 @@
     def test_preprocess_security(self):
         plan = self._prepare_plan('Any ETN,COUNT(X) GROUPBY ETN '
                                   'WHERE X is ET, ET name ETN')
-        plan.session = self.user_groups_session('users')
+        plan.cnx = self.user_groups_session('users')
         union = plan.rqlst
         plan.preprocess(union)
         self.assertEqual(len(union.children), 1)
@@ -210,7 +210,7 @@
 
     def test_preprocess_security_aggregat(self):
         plan = self._prepare_plan('Any MAX(X)')
-        plan.session = self.user_groups_session('users')
+        plan.cnx = self.user_groups_session('users')
         union = plan.rqlst
         plan.preprocess(union)
         self.assertEqual(len(union.children), 1)