# HG changeset patch # User Julien Cristau # Date 1391005789 -3600 # Node ID 1263f125879652973c3ac1fac1c5e529b1a75051 # Parent 540cb068a7f955a474a50e468bfdc5b43df5896a [server] rename session to cnx in querier and plan They don't actually need a session, so let's make that clear. diff -r 540cb068a7f9 -r 1263f1258796 server/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 diff -r 540cb068a7f9 -r 1263f1258796 server/ssplanner.py --- 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): diff -r 540cb068a7f9 -r 1263f1258796 server/test/unittest_querier.py --- 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)