cubicweb/server/querier.py
changeset 12889 bbf3e56b43fe
parent 12888 24a20d2b8c84
child 12931 6eae252361e5
equal deleted inserted replaced
12888:24a20d2b8c84 12889:bbf3e56b43fe
   152 # Plans #######################################################################
   152 # Plans #######################################################################
   153 
   153 
   154 class ExecutionPlan(object):
   154 class ExecutionPlan(object):
   155     """the execution model of a rql query, composed of querier steps"""
   155     """the execution model of a rql query, composed of querier steps"""
   156 
   156 
   157     def __init__(self, querier, rqlst, args, cnx):
   157     def __init__(self, schema, rqlst, args, cnx):
       
   158         self.schema = schema
   158         # original rql syntax tree
   159         # original rql syntax tree
   159         self.rqlst = rqlst
   160         self.rqlst = rqlst
   160         self.args = args or {}
   161         self.args = args or {}
   161         # cnx executing the query
   162         # cnx executing the query
   162         self.cnx = cnx
   163         self.cnx = cnx
   163         # execution steps
   164         # execution steps
   164         self.steps = []
   165         self.steps = []
   165         self.querier = querier
       
   166         # tracing token for debugging
   166         # tracing token for debugging
   167         self.rql_query_tracing_token = None
   167         self.rql_query_tracing_token = None
   168 
   168 
   169     def add_step(self, step):
   169     def add_step(self, step):
   170         """add a step to the plan"""
   170         """add a step to the plan"""
   209                     self.cnx.transaction_data[key] = (union, self.args)
   209                     self.cnx.transaction_data[key] = (union, self.args)
   210         else:
   210         else:
   211             noinvariant = ()
   211             noinvariant = ()
   212         if cached is None:
   212         if cached is None:
   213             self.cnx.vreg.rqlhelper.simplify(union)
   213             self.cnx.vreg.rqlhelper.simplify(union)
   214             RQLAnnotator(self.querier.schema).annotate(union)
   214             RQLAnnotator(self.schema).annotate(union)
   215             set_qdata(self.querier.schema.rschema, union, noinvariant)
   215             set_qdata(self.schema.rschema, union, noinvariant)
   216         if union.has_text_query:
   216         if union.has_text_query:
   217             self.cache_key = None
   217             self.cache_key = None
   218 
   218 
   219     def _insert_security(self, union):
   219     def _insert_security(self, union):
   220         noinvariant = set()
   220         noinvariant = set()
   306         for mainvarname, rschema, newvarname in insertedvars:
   306         for mainvarname, rschema, newvarname in insertedvars:
   307             nvartype = str(rschema.objects(solutions[0][mainvarname])[0])
   307             nvartype = str(rschema.objects(solutions[0][mainvarname])[0])
   308             for sol in solutions:
   308             for sol in solutions:
   309                 sol[newvarname] = nvartype
   309                 sol[newvarname] = nvartype
   310         select.clean_solutions(solutions)
   310         select.clean_solutions(solutions)
   311         add_types_restriction(self.querier.schema, select)
   311         add_types_restriction(self.schema, select)
   312         self.cnx.vreg.rqlhelper.annotate(rqlst)
   312         self.cnx.vreg.rqlhelper.annotate(rqlst)
   313         self.preprocess(rqlst, security=False)
   313         self.preprocess(rqlst, security=False)
   314         return rqlst
   314         return rqlst
   315 
   315 
   316 
   316 
   317 class InsertPlan(ExecutionPlan):
   317 class InsertPlan(ExecutionPlan):
   318     """an execution model specific to the INSERT rql query
   318     """an execution model specific to the INSERT rql query
   319     """
   319     """
   320 
   320 
   321     def __init__(self, querier, rqlst, args, cnx):
   321     def __init__(self, schema, rqlst, args, cnx):
   322         ExecutionPlan.__init__(self, querier, rqlst, args, cnx)
   322         ExecutionPlan.__init__(self, schema, rqlst, args, cnx)
   323         # save originally selected variable, we may modify this
   323         # save originally selected variable, we may modify this
   324         # dictionary for substitution (query parameters)
   324         # dictionary for substitution (query parameters)
   325         self.selected = rqlst.selection
   325         self.selected = rqlst.selection
   326         # list of rows of entities definition (ssplanner.EditedEntity)
   326         # list of rows of entities definition (ssplanner.EditedEntity)
   327         self.e_defs = [[]]
   327         self.e_defs = [[]]
   337         self.e_defs[-1].append(edef)
   337         self.e_defs[-1].append(edef)
   338 
   338 
   339     def add_relation_def(self, rdef):
   339     def add_relation_def(self, rdef):
   340         """add an relation definition to build"""
   340         """add an relation definition to build"""
   341         edef, rtype, value = rdef
   341         edef, rtype, value = rdef
   342         if self.querier.schema[rtype].rule:
   342         if self.schema[rtype].rule:
   343             raise QueryError("'%s' is a computed relation" % rtype)
   343             raise QueryError("'%s' is a computed relation" % rtype)
   344         self.r_defs.add(rdef)
   344         self.r_defs.add(rdef)
   345         if not isinstance(edef, int):
   345         if not isinstance(edef, int):
   346             self._r_subj_index.setdefault(edef, []).append(rdef)
   346             self._r_subj_index.setdefault(edef, []).append(rdef)
   347         if not isinstance(value, int):
   347         if not isinstance(value, int):
   485                     cache.pop(('%s X WHERE X eid %s' % (etype, eid),), None)
   485                     cache.pop(('%s X WHERE X eid %s' % (etype, eid),), None)
   486 
   486 
   487     def plan_factory(self, rqlst, args, cnx):
   487     def plan_factory(self, rqlst, args, cnx):
   488         """create an execution plan for an INSERT RQL query"""
   488         """create an execution plan for an INSERT RQL query"""
   489         if rqlst.TYPE == 'insert':
   489         if rqlst.TYPE == 'insert':
   490             return InsertPlan(self, rqlst, args, cnx)
   490             return InsertPlan(self.schema, rqlst, args, cnx)
   491         return ExecutionPlan(self, rqlst, args, cnx)
   491         return ExecutionPlan(self.schema, rqlst, args, cnx)
   492 
   492 
   493     @statsd_timeit
   493     @statsd_timeit
   494     def execute(self, cnx, rql, args=None, build_descr=True):
   494     def execute(self, cnx, rql, args=None, build_descr=True):
   495         """execute a rql query, return resulting rows and their description in
   495         """execute a rql query, return resulting rows and their description in
   496         a `ResultSet` object
   496         a `ResultSet` object