27 |
27 |
28 from logilab.common.cache import Cache |
28 from logilab.common.cache import Cache |
29 from logilab.common.compat import any |
29 from logilab.common.compat import any |
30 from rql import RQLSyntaxError |
30 from rql import RQLSyntaxError |
31 from rql.stmts import Union, Select |
31 from rql.stmts import Union, Select |
32 from rql.nodes import Relation, VariableRef, Constant, SubQuery |
32 from rql.nodes import Relation, VariableRef, Constant, SubQuery, Function |
33 |
33 |
34 from cubicweb import Unauthorized, QueryError, UnknownEid, typed_eid |
34 from cubicweb import Unauthorized, QueryError, UnknownEid, typed_eid |
35 from cubicweb import server |
35 from cubicweb import server |
36 from cubicweb.rset import ResultSet |
36 from cubicweb.rset import ResultSet |
37 |
37 |
48 """return a sql schema to store RQL query result""" |
48 """return a sql schema to store RQL query result""" |
49 for i, term in enumerate(selected): |
49 for i, term in enumerate(selected): |
50 key = term.as_string() |
50 key = term.as_string() |
51 value = '%s.C%s' % (table, i) |
51 value = '%s.C%s' % (table, i) |
52 if varmap.get(key, value) != value: |
52 if varmap.get(key, value) != value: |
53 raise Exception('variable name conflict on %s' % key) |
53 raise Exception('variable name conflict on %s: got %s / %s' |
|
54 % (key, value, varmap)) |
54 varmap[key] = value |
55 varmap[key] = value |
55 |
56 |
56 # permission utilities ######################################################## |
57 # permission utilities ######################################################## |
57 |
58 |
58 def check_no_password_selected(rqlst): |
59 def check_no_password_selected(rqlst): |
283 selected = set(vref.name for vref in aliases) |
284 selected = set(vref.name for vref in aliases) |
284 # now copy original selection and groups |
285 # now copy original selection and groups |
285 for term in origselection: |
286 for term in origselection: |
286 newselect.append_selected(term.copy(newselect)) |
287 newselect.append_selected(term.copy(newselect)) |
287 if select.orderby: |
288 if select.orderby: |
288 newselect.set_orderby([s.copy(newselect) for s in select.orderby]) |
289 sortterms = [] |
|
290 for sortterm in select.orderby: |
|
291 sortterms.append(sortterm.copy(newselect)) |
|
292 for fnode in sortterm.get_nodes(Function): |
|
293 if fnode.name == 'FTIRANK': |
|
294 # we've to fetch the has_text relation as well |
|
295 var = fnode.children[0].variable |
|
296 rel = iter(var.stinfo['ftirels']).next() |
|
297 assert not rel.ored(), 'unsupported' |
|
298 newselect.add_restriction(rel.copy(newselect)) |
|
299 # remove relation from the orig select and |
|
300 # cleanup variable stinfo |
|
301 rel.parent.remove(rel) |
|
302 var.stinfo['ftirels'].remove(rel) |
|
303 var.stinfo['relations'].remove(rel) |
|
304 # XXX not properly re-annotated after security insertion? |
|
305 newvar = newselect.get_variable(var.name) |
|
306 newvar.stinfo.setdefault('ftirels', set()).add(rel) |
|
307 newvar.stinfo.setdefault('relations', set()).add(rel) |
|
308 newselect.set_orderby(sortterms) |
289 _expand_selection(select.orderby, selected, aliases, select, newselect) |
309 _expand_selection(select.orderby, selected, aliases, select, newselect) |
290 select.orderby = () # XXX dereference? |
310 select.orderby = () # XXX dereference? |
291 if select.groupby: |
311 if select.groupby: |
292 newselect.set_groupby([g.copy(newselect) for g in select.groupby]) |
312 newselect.set_groupby([g.copy(newselect) for g in select.groupby]) |
293 _expand_selection(select.groupby, selected, aliases, select, newselect) |
313 _expand_selection(select.groupby, selected, aliases, select, newselect) |
560 # some cache usage stats |
580 # some cache usage stats |
561 self.cache_hit, self.cache_miss = 0, 0 |
581 self.cache_hit, self.cache_miss = 0, 0 |
562 # rql parsing / analysing helper |
582 # rql parsing / analysing helper |
563 self.solutions = repo.vreg.solutions |
583 self.solutions = repo.vreg.solutions |
564 rqlhelper = repo.vreg.rqlhelper |
584 rqlhelper = repo.vreg.rqlhelper |
|
585 # set backend on the rql helper, will be used for function checking |
|
586 rqlhelper.backend = repo.config.sources()['system']['db-driver'] |
565 self._parse = rqlhelper.parse |
587 self._parse = rqlhelper.parse |
566 self._annotate = rqlhelper.annotate |
588 self._annotate = rqlhelper.annotate |
567 # rql planner |
589 # rql planner |
568 # note: don't use repo.sources, may not be built yet, and also "admin" |
590 # note: don't use repo.sources, may not be built yet, and also "admin" |
569 # isn't an actual source |
591 # isn't an actual source |