136 # index of temporary tables created during execution |
136 # index of temporary tables created during execution |
137 self.temp_tables = {} |
137 self.temp_tables = {} |
138 # various resource accesors |
138 # various resource accesors |
139 self.querier = querier |
139 self.querier = querier |
140 self.schema = querier.schema |
140 self.schema = querier.schema |
141 self.rqlhelper = querier._rqlhelper |
|
142 self.sqlannotate = querier.sqlgen_annotate |
141 self.sqlannotate = querier.sqlgen_annotate |
|
142 self.rqlhelper = session.vreg.rqlhelper |
143 |
143 |
144 def annotate_rqlst(self): |
144 def annotate_rqlst(self): |
145 if not self.rqlst.annotated: |
145 if not self.rqlst.annotated: |
146 self.rqlhelper.annotate(self.rqlst) |
146 self.rqlhelper.annotate(self.rqlst) |
147 |
147 |
263 if not lcheckdef: |
263 if not lcheckdef: |
264 continue |
264 continue |
265 myrqlst = select.copy(solutions=lchecksolutions) |
265 myrqlst = select.copy(solutions=lchecksolutions) |
266 myunion.append(myrqlst) |
266 myunion.append(myrqlst) |
267 # in-place rewrite + annotation / simplification |
267 # in-place rewrite + annotation / simplification |
|
268 lcheckdef = [((varmap, 'X'), rqlexprs) |
|
269 for varmap, rqlexprs in lcheckdef] |
268 rewrite(myrqlst, lcheckdef, lchecksolutions, self.args) |
270 rewrite(myrqlst, lcheckdef, lchecksolutions, self.args) |
269 noinvariant.update(noinvariant_vars(restricted, myrqlst, nbtrees)) |
271 noinvariant.update(noinvariant_vars(restricted, myrqlst, nbtrees)) |
270 if () in localchecks: |
272 if () in localchecks: |
271 select.set_possible_types(localchecks[()]) |
273 select.set_possible_types(localchecks[()]) |
272 add_types_restriction(self.schema, select) |
274 add_types_restriction(self.schema, select) |
522 # instance schema |
524 # instance schema |
523 self.set_schema(schema) |
525 self.set_schema(schema) |
524 |
526 |
525 def set_schema(self, schema): |
527 def set_schema(self, schema): |
526 self.schema = schema |
528 self.schema = schema |
|
529 repo = self._repo |
527 # rql parsing / analysing helper |
530 # rql parsing / analysing helper |
528 self._rqlhelper = RQLHelper(schema, special_relations={'eid': 'uid', |
531 self.solutions = repo.vreg.solutions |
529 'has_text': 'fti'}) |
532 self._rql_cache = Cache(repo.config['rql-cache-size']) |
530 self._rql_cache = Cache(self._repo.config['rql-cache-size']) |
|
531 self.cache_hit, self.cache_miss = 0, 0 |
533 self.cache_hit, self.cache_miss = 0, 0 |
532 # rql planner |
534 # rql planner |
533 # note: don't use repo.sources, may not be built yet, and also "admin" |
535 # note: don't use repo.sources, may not be built yet, and also "admin" |
534 # isn't an actual source |
536 # isn't an actual source |
535 if len([uri for uri in self._repo.config.sources() if uri != 'admin']) < 2: |
537 rqlhelper = repo.vreg.rqlhelper |
|
538 self._parse = rqlhelper.parse |
|
539 self._annotate = rqlhelper.annotate |
|
540 if len([uri for uri in repo.config.sources() if uri != 'admin']) < 2: |
536 from cubicweb.server.ssplanner import SSPlanner |
541 from cubicweb.server.ssplanner import SSPlanner |
537 self._planner = SSPlanner(schema, self._rqlhelper) |
542 self._planner = SSPlanner(schema, rqlhelper) |
538 else: |
543 else: |
539 from cubicweb.server.msplanner import MSPlanner |
544 from cubicweb.server.msplanner import MSPlanner |
540 self._planner = MSPlanner(schema, self._rqlhelper) |
545 self._planner = MSPlanner(schema, rqlhelper) |
541 # sql generation annotator |
546 # sql generation annotator |
542 self.sqlgen_annotate = SQLGenAnnotator(schema).annotate |
547 self.sqlgen_annotate = SQLGenAnnotator(schema).annotate |
543 |
548 |
544 def parse(self, rql, annotate=False): |
549 def parse(self, rql, annotate=False): |
545 """return a rql syntax tree for the given rql""" |
550 """return a rql syntax tree for the given rql""" |
546 try: |
551 try: |
547 return self._rqlhelper.parse(unicode(rql), annotate=annotate) |
552 return self._parse(unicode(rql), annotate=annotate) |
548 except UnicodeError: |
553 except UnicodeError: |
549 raise RQLSyntaxError(rql) |
554 raise RQLSyntaxError(rql) |
550 |
|
551 def solutions(self, session, rqlst, args): |
|
552 assert session is not None |
|
553 def type_from_eid(eid, type_from_eid=self._repo.type_from_eid, |
|
554 session=session): |
|
555 return type_from_eid(eid, session) |
|
556 self._rqlhelper.compute_solutions(rqlst, {'eid': type_from_eid}, args) |
|
557 |
555 |
558 def plan_factory(self, rqlst, args, session): |
556 def plan_factory(self, rqlst, args, session): |
559 """create an execution plan for an INSERT RQL query""" |
557 """create an execution plan for an INSERT RQL query""" |
560 if rqlst.TYPE == 'insert': |
558 if rqlst.TYPE == 'insert': |
561 return InsertPlan(self, rqlst, args, session) |
559 return InsertPlan(self, rqlst, args, session) |
640 check_no_password_selected(select) |
638 check_no_password_selected(select) |
641 # on select query, always copy the cached rqlst so we don't have to |
639 # on select query, always copy the cached rqlst so we don't have to |
642 # bother modifying it. This is not necessary on write queries since |
640 # bother modifying it. This is not necessary on write queries since |
643 # a new syntax tree is built from them. |
641 # a new syntax tree is built from them. |
644 rqlst = rqlst.copy() |
642 rqlst = rqlst.copy() |
645 self._rqlhelper.annotate(rqlst) |
643 self._annotate(rqlst) |
646 # make an execution plan |
644 # make an execution plan |
647 plan = self.plan_factory(rqlst, args, session) |
645 plan = self.plan_factory(rqlst, args, session) |
648 plan.cache_key = cachekey |
646 plan.cache_key = cachekey |
649 self._planner.build_plan(plan) |
647 self._planner.build_plan(plan) |
650 # execute the plan |
648 # execute the plan |