def test_as_string_now_today_null(self): tree = parse(u"Any X WHERE X name NULL") self.assertEqual(tree.as_string(), 'Any X WHERE X name NULL') tree = parse(u"Any X WHERE X creation_date NOW") self.assertEqual(tree.as_string(), 'Any X WHERE X creation_date NOW') tree = parse(u"Any X WHERE X creation_date TODAY") self.assertEqual(tree.as_string(), 'Any X WHERE X creation_date TODAY')
def build_suggestions(self, user_rql): """return a list of suggestions to complete `user_rql` :param user_rql: an incomplete RQL query """ req = self._cw try: if 'WHERE' not in user_rql: # don't try to complete if there's no restriction return [] variables, restrictions = [part.strip() for part in user_rql.split('WHERE', 1)] if ',' in restrictions: restrictions, incomplete_part = restrictions.rsplit(',', 1) user_rql = '%s WHERE %s' % (variables, restrictions) else: restrictions, incomplete_part = '', restrictions user_rql = variables select = parse(user_rql, print_errors=False).children[0] req.vreg.rqlhelper.annotate(select) req.vreg.solutions(req, select, {}) if restrictions: return ['%s, %s' % (user_rql, suggestion) for suggestion in self.rql_build_suggestions(select, incomplete_part)] else: return ['%s WHERE %s' % (user_rql, suggestion) for suggestion in self.rql_build_suggestions(select, incomplete_part)] except Exception as exc: # we never want to crash self.debug('failed to build suggestions: %s', exc) return []
def preprocess_query(self, uquery): rqlst = parse(uquery, print_errors=False) schema = self._cw.vreg.schema # rql syntax tree will be modified in place if necessary translate_rql_tree(rqlst, trmap(self._cw.vreg.config, schema, self._cw.lang), schema) return rqlst.as_string(),
def test_subquery_callfunc_2(self): rql = ('Any X,S,L WHERE ' 'X in_state S WITH X, L BEING (Any X,MAX(L) GROUPBY X WHERE ' 'X is CWUser, T wf_info_for X, T creation_date L)') rqlst = parse(rql) select, col = rqlst.locate_subquery(0, 'CWUser', None) result = list(attr_desc_iterator(select, col, 0)) self.assertEqual(result, [(1, 'in_state', 'subject')])
def test_subquery_callfunc(self): rql = ('Any A,B,C,COUNT(D) GROUPBY A,B,C WITH A,B,C,D BEING ' '(Any YEAR(CD), MONTH(CD), S, X WHERE X is CWUser, ' 'X creation_date CD, X in_state S)') rqlst = parse(rql) select, col = rqlst.locate_subquery(2, 'CWUser', None) result = list(attr_desc_iterator(select, col, 2)) self.assertEqual(result, [])
def test_iknown_values_2(self): tree = parse( 'Any X where X name "turlututu", Y know X, Y name "chapo pointu"' ).children[0] varrefs = list(tree.iget_nodes(nodes.VariableRef)) self.assertEqual(len(varrefs), 5) for varref in varrefs: self.assertIsInstance(varref, nodes.VariableRef) self.assertEqual(sorted(x.name for x in varrefs), ['X', 'X', 'X', 'Y', 'Y'])
def test_relations_description_indexed(self): """tests relations_description() function""" queries = { 'Any C,U,P,L,M where C is Company, C employs P, U is CWUser, U login L, U mail M': {0: [(2, 'employs', 'subject')], 1: [(3, 'login', 'subject'), (4, 'mail', 'subject')]}, } for rql, results in queries.items(): for idx, relations in results.items(): result = list(attr_desc_iterator(parse(rql).children[0], idx, idx)) self.assertEqual(result, relations)
def _parse(self, rql, normrql=None): tree = parse(rql + ';') tree.check_references() if normrql is None: normrql = rql self.assertEqual(tree.as_string(), normrql) # just check repr() doesn't raise an exception repr(tree) copy = tree.copy() self.assertEqual(copy.as_string(), normrql) copy.check_references() return tree
def test_undefine_1(self): rqlst = parse('Person X, Y WHERE X travaille_pour Y') orig = rqlst.as_string() rqlst.save_state() rqlst.children[0].undefine_variable( rqlst.children[0].defined_vars['Y']) # check operations self.assertEqual(rqlst.as_string(), 'Any X WHERE X is Person') # check references before recovering rqlst.check_references() rqlst.recover() # check equivalence self.assertEqual(rqlst.as_string(), orig) # check references after recovering rqlst.check_references()
def test_relations_description(self): """tests relations_description() function""" queries = { 'Any U,L,M where U is CWUser, U login L, U mail M': [ (1, 'login', 'subject'), (2, 'mail', 'subject')], 'Any U,L,M where U is CWUser, L is Foo, U mail M': [ (2, 'mail', 'subject')], 'Any C,P where C is Company, C employs P': [ (1, 'employs', 'subject')], 'Any C,P where C is Company, P employed_by P': [], 'Any C where C is Company, C employs P': [], } for rql, relations in queries.items(): result = list(attr_desc_iterator(parse(rql).children[0], 0, 0)) self.assertEqual((rql, result), (rql, relations))
def _etype_relink_clones(self, etype, queryargs, relations, deferred_relations): etype_rql = self._complete_rql(etype) for rtype in self.clonable_rtypes(etype): self.info(' rtype %s', rtype) # NOTE: use rqlst.save() / rqlst.recover() ? etype_rqlst = parse(etype_rql).children[0] # here, we've got something like: Any X WHERE X <container> C, ... _add_rqlst_restriction(etype_rqlst, rtype) # now, we've got something like: Any X,Y WHERE X <container> C, ..., X <rtype> Y linked_rset = self._cw.execute(etype_rqlst, queryargs) for ceid, linked_eid in linked_rset: if rtype in self._specially_handled_rtypes: deferred_relations.append((rtype, ceid, linked_eid)) else: relations[rtype].append((ceid, linked_eid))
def test_undefine_2(self): rqlst = parse('Person X') orig = rqlst.as_string() rqlst.save_state() rqlst.children[0].undefine_variable( rqlst.children[0].defined_vars['X']) var = rqlst.children[0].make_variable() rqlst.children[0].add_selected(var) # check operations self.assertEqual(rqlst.as_string(), 'Any A') # check references before recovering rqlst.check_references() rqlst.recover() # check equivalence self.assertEqual(rqlst.as_string(), orig) # check references after recovering rqlst.check_references()
def test_selected3(self): rqlst = parse('Any lower(N) WHERE X is Person, X name N') orig = rqlst.as_string() rqlst.save_state() select = rqlst.children[0] var = select.make_variable() select.remove_selected(select.selection[0]) select.add_selected(var) # check operations self.assertEqual(rqlst.as_string(), 'Any %s WHERE X is Person, X name N' % var.name) # check references before recovering rqlst.check_references() rqlst.recover() # check equivalence after recovering self.assertEqual(rqlst.as_string(), orig) # check references after recovering rqlst.check_references()
def test_remove_exists(self): rql_request = ('Any U,COUNT(P) GROUPBY U WHERE U is CWUser, ' 'P? patch_reviewer U, EXISTS(P in_state S AND ' 'S name "pouet")') rqlst = parse(rql_request).children[0] orig = rqlst.as_string() rqlst.save_state() n = [r for r in rqlst.get_nodes(Exists)][0].query rqlst.remove_node(n) # check operations self.assertEqual( rqlst.as_string(), 'Any U,COUNT(P) GROUPBY U WHERE U is CWUser, P? patch_reviewer U') # check references before recovering rqlst.check_references() rqlst.recover() # check equivalence self.assertEqual(rqlst.as_string(), orig) # check references after recovering rqlst.check_references()
def _etype_fetch_rqlst(self, etype, completefragment=''): """ returns an rqlst ready to be executed, plus a sequence of all attributes or inlined rtypes that will be fetched by the rql, plus a set of the inlined rtypes """ base_rql = self._complete_rql(etype) + completefragment # modify base_rql to fetch all attributes / inlined rtypes rqlst = parse(base_rql).children[0] # a dict from rtype to rql variable already_used_rtypes = dict(_iter_mainvar_relations(rqlst)) # running without metadata hooks: we must handle some rtypes here # we also will loose: is_instance_of, cwuri, has_text, eid, is, identity no_copy_meta = self._no_copy_meta # keep an ordered-list of selected rtypes fetched_rtypes = [] inlined_rtypes = set() # NOTE: we don't use entity_class.fetch_rqlst() because: # - fetch_rqlst() needs user to check some read permissions (we # don't need this and it even might fail because fetch_rqlst() # is totally unaware of local perms) # - fetch_rqlst() recurses on target etypes: we don't want this for rschema in self._cw.vreg.schema[etype].subject_relations(): rtype = rschema.type if rtype in self.rtypes_to_skip or rtype in VIRTUAL_RTYPES: continue if rschema.meta and rtype in no_copy_meta: continue if not rschema.final and not rschema.inlined: continue fetched_rtypes.append(rtype) if rschema.inlined: inlined_rtypes.add(rtype) # check if this rtype is already used in base_rql's restrictions # in which case the only thing to do is to select corresponding var if rtype in already_used_rtypes: rqlst.append_selected(already_used_rtypes[rtype]) else: # otherwise, add a new restriction and select the new var _add_rqlst_restriction(rqlst, rtype, optional=rschema.inlined) return rqlst, fetched_rtypes, inlined_rtypes
def test_as_string(self): tree = parse("SET X know Y WHERE X friend Y;") self.assertEqual(tree.as_string(), 'SET X know Y WHERE X friend Y') tree = parse("Person X") self.assertEqual(tree.as_string(), 'Any X WHERE X is Person') tree = parse(u"Any X WHERE X has_text 'héhé'") self.assertEqual(tree.as_string(), u'Any X WHERE X has_text "héhé"') tree = parse(u"Any X WHERE X has_text %(text)s") self.assertEqual(tree.as_string({'text': u'héhé'}), u'Any X WHERE X has_text "héhé"') tree = parse(u"Any X WHERE X has_text %(text)s") self.assertEqual(tree.as_string({'text': u'hé"hé'}), u'Any X WHERE X has_text "hé\\"hé"') tree = parse(u"Any X WHERE X has_text %(text)s") self.assertEqual(tree.as_string({'text': u'hé"\'hé'}), u'Any X WHERE X has_text "hé\\"\'hé"')
def _container_relink(self, orig_to_clone): """ handle subject relations of the container - this is handled specially because attributes have already been set we partition subject relations in two sets: * those that are already set (typically .owned_by, .created_by, ...) * those that must yet be cloned """ deferred_relations = [] relations = defaultdict(list) queryargs = self._queryargs() clone = self.entity etype = clone.e_schema.type etype_rql = 'Any X WHERE X is %s, X eid %s' % ( etype, self.orig_container_eid) skiprtypes = set(self.rtypes_to_skip) if self.clone_rtype: skiprtypes.add(self.clone_rtype) clone_subject_relations = set(rschema.type for rschema in clone.e_schema.subject_relations() if not rschema.final) for rtype in self.clonable_rtypes(etype): if rtype in clone_subject_relations: if self._cw.execute('Any Y LIMIT 1 WHERE X eid %%(clone)s, X %(rtype)s Y' % {'rtype': rtype}, {'clone': clone.eid}): continue etype_rqlst = parse(etype_rql).children[0] _add_rqlst_restriction(etype_rqlst, rtype) linked_rset = self._cw.execute(etype_rqlst, queryargs) for ceid, linked_eid in linked_rset: if rtype in self._specially_handled_rtypes: deferred_relations.append((rtype, ceid, linked_eid)) else: relations[rtype].append((ceid, linked_eid)) self._flush_deferred(deferred_relations, orig_to_clone) return relations
"Relation": Relation, "Comparison": Comparison, "And": AND, "Or": OR, "VariableRef": VariableRef, "Insert": Insert, "Select": Select, "Delete": Delete, "Update": Update, "MathExpression": MathExpression, "Sort": Sort, "Sortterm": SortTerm, } f = file(sys.argv[1]) for l in f: # print(l, end="") x1 = cparse(l, builder) x2 = parse(l) l = l.strip() d1 = make_canon_dict(x1) d2 = make_canon_dict(x2) t = d1 == d2 print('%s : "%s"' % (t, l)) if not t: print("CPP", x1) pprint(d1) print("PYT", x2) pprint(d2)
def test_methods_4(self): tree = parse('Delete Person X', {}) self.visitor.visit(tree)
def test_methods_3(self): tree = parse( 'Set X nom "yo" WHERE X is Person', {'Person': nodes.Constant('Person', 'etype')}, ) self.visitor.visit(tree)
# copyright 2004-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved. # contact http://www.logilab.fr/ -- mailto:[email protected] # # This file is part of rql. # # rql is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 2.1 of the License, or (at your option) # any later version. # # rql is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License along # with rql. If not, see <http://www.gnu.org/licenses/>. from __future__ import print_function from rql import parse import sys f = open(sys.argv[1]) for l in f: parse(l) print(".", end="")
def test_iknown_values_1(self): tree = parse('Any X where X name "turlututu"').children[0] constants = list(tree.iget_nodes(nodes.Constant)) self.assertEqual(len(constants), 1) self.assertEqual(isinstance(constants[0], nodes.Constant), 1) self.assertEqual(constants[0].value, 'turlututu')
def test_repr_encoding(self): tree = parse(u'Any N where NOT N has_text "bidüle"') repr(tree)
def test_methods_2(self): tree = parse('Insert Person X', {}) self.visitor.visit(tree)
def test_as_string_no_encoding(self): tree = parse(u"Any X WHERE X has_text 'héhé'") self.assertEqual(tree.as_string(), u'Any X WHERE X has_text "héhé"') tree = parse(u"Any X WHERE X has_text %(text)s") self.assertEqual(tree.as_string(kwargs={'text': u'héhé'}), u'Any X WHERE X has_text "héhé"')
def parse(self, string, print_errors=False): try: return parse(string, print_errors) except Exception: raise
def test_methods_1(self): tree = parse( 'Any X where X name "turlututu", X born <= TODAY - 2 OR X born = NULL', {}) self.visitor.visit(tree)