Add a "should_register_op" class attribute to ScopeNode
This a follow-up on changeset a0bf7565501f which introduce usage of this
attribute in set_having() method. Sometimes, derived would classes
implement this method (e.g. through EditableMixIn or directly, like
Union) but some statement would not (e.g. Delete). So this breaks any
mutable query using an HAVING clause. For instance, in cubicweb:
self = <unittest_querier.QuerierTC testMethod=test_update_having>
def test_update_having(self):
peid1 = self.qexecute("INSERT Personne Y: Y nom 'hop', Y tel 1")[0][0]
peid2 = self.qexecute("INSERT Personne Y: Y nom 'hop', Y tel 2")[0][0]
> rset = self.qexecute("SET X tel 3 WHERE X tel TEL HAVING TEL&1=1")
cubicweb/server/test/unittest_querier.py:1354:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
cubicweb/devtools/repotest.py:193: in qexecute
return self.o.execute(cnx, rql, args, build_descr)
cubicweb/server/sqlutils.py:488: in new_execute
rset = base_execute(*args, **kwargs)
cubicweb/statsd_logger.py:135: in __call__
return self.callable(*args, **kw)
cubicweb/server/querier.py:532: in execute
rqlst, cachekey = self.rql_cache.get(cnx, rql, args)
cubicweb/server/querier.py:659: in get
rqlst = self._parse(rql)
cubicweb/server/querier.py:629: in parse
return parse(text_type(rql), annotate=annotate)
.tox/py27-server/local/lib/python2.7/site-packages/rql/__init__.py:91: in parse
rqlst = parse(rqlstring, False)
.tox/py27-server/local/lib/python2.7/site-packages/rql/__init__.py:213: in parse
return parser.goal()
.tox/py27-server/local/lib/python2.7/site-packages/rql/parser.py:123: in goal
update = self.update(Set(), _context)
.tox/py27-server/local/lib/python2.7/site-packages/rql/parser.py:167: in update
having = self.having(R, _context)
.tox/py27-server/local/lib/python2.7/site-packages/rql/parser.py:243: in having
S.set_having([logical_expr])
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = SET Relation(VarRef(X) tel = 3) WHERE Relation(VarRef(X) tel = VarRef(TEL))
terms = [= (VarRef(TEL) & 1), 1]
def set_having(self, terms):
> if self.should_register_op:
E AttributeError: 'Set' object has no attribute 'should_register_op'
.tox/py27-server/local/lib/python2.7/site-packages/rql/stmts.py:82: AttributeError
So, we simply add a class attribute with a None value so that the
interface of this ScopeNode class is at least self-consistent.
Adding a non-regression test with a DELETE and a SET queries.
(Note that most existing non-regression tests do not contain assertions,
they just call functions in the hope they do not crash; the new test
just follows this pattern as I don't know what to check.)
# -*- coding: iso-8859-1 -*-
# copyright 2004-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# 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/>.
import sys
import itertools
from datetime import date, datetime
from logilab.common.testlib import TestCase, unittest_main
from rql import nodes, stmts, parse, BadRQLQuery, RQLHelper, RQLException, CoercionError
from unittest_analyze import DummySchema
schema = DummySchema()
from rql.stcheck import RQLSTAnnotator
annotator = RQLSTAnnotator(schema, {})
helper = RQLHelper(schema, None, {'eid': 'uid'})
def sparse(rql):
tree = helper.parse(rql)
helper.compute_solutions(tree)
return tree
class EtypeFromPyobjTC(TestCase):
def test_bool(self):
self.assertEqual(nodes.etype_from_pyobj(True), 'Boolean')
self.assertEqual(nodes.etype_from_pyobj(False), 'Boolean')
def test_int(self):
self.assertEqual(nodes.etype_from_pyobj(0), 'Int')
if sys.version_info < (3,):
l = long
self.assertEqual(nodes.etype_from_pyobj(l('1L')), 'Int')
def test_float(self):
self.assertEqual(nodes.etype_from_pyobj(0.), 'Float')
def test_datetime(self):
self.assertEqual(nodes.etype_from_pyobj(datetime.now()), 'Datetime')
self.assertEqual(nodes.etype_from_pyobj(date.today()), 'Date')
def test_string(self):
self.assertEqual(nodes.etype_from_pyobj('hop'), 'String')
self.assertEqual(nodes.etype_from_pyobj(u'hop'), 'String')
class TypesRestrictionNodesTest(TestCase):
def setUp(self):
self.parse = helper.parse
self.simplify = helper.simplify
def test_add_is_type_restriction(self):
tree = self.parse("Any X WHERE X is Person, X name ILIKE 'A%'")
select = tree.children[0]
x = next(select.get_selected_variables())
self.assertRaises(RQLException, select.add_type_restriction, x.variable, 'Babar')
select.add_type_restriction(x.variable, 'Person')
self.assertEqual(tree.as_string(), 'Any X WHERE X is Person, X name ILIKE "A%"')
def test_add_new_is_type_restriction_in(self):
tree = self.parse("Any X WHERE X is IN(Person, Company), X name ILIKE 'A%'")
select = tree.children[0]
x = next(select.get_selected_variables())
select.add_type_restriction(x.variable, 'Company')
# implementation is KISS (the IN remains)
self.assertEqual(tree.as_string(), 'Any X WHERE X is IN(Company), X name ILIKE "A%"')
def test_add_new_is_type_restriction_in_nonregr(self):
tree = self.parse('Any X WHERE X is IN(Person, Company, Student)')
select = tree.children[0]
x = next(select.get_selected_variables())
select.add_type_restriction(x.variable, 'Person')
self.assertEqual(tree.as_string(), 'Any X WHERE X is IN(Person)')
def test_add_is_in_type_restriction(self):
tree = self.parse("Any X WHERE X is IN(Person, Company), X name ILIKE 'A%'")
select = tree.children[0]
x = next(select.get_selected_variables())
self.assertRaises(RQLException, select.add_type_restriction, x.variable, 'Babar')
self.assertEqual(tree.as_string(), 'Any X WHERE X is IN(Person, Company), X name ILIKE "A%"')
def test_add_is_in_type_restriction_multiple(self):
tree = self.parse("Any X WHERE X is IN(Person, Company, Student, Address), "
" X name ILIKE 'A%'")
select = tree.children[0]
x = next(select.get_selected_variables())
add_restr = select.add_type_restriction
self.assertRaises(RQLException, add_restr, x.variable, 'Babar')
self.assertRaises(RQLException, add_restr, x.variable, ['Babar'])
self.assertRaises(RQLException, add_restr, x.variable,
['Babar', 'Person'])
add_restr(x.variable, ['Company', 'Student'])
self.assertEqual(tree.as_string(),
'Any X WHERE X is IN(Company, Student), X name ILIKE "A%"')
def test_add_is_type_restriction_on_is_instance_of(self):
select = self.parse("Any X WHERE X is_instance_of Person, X name ILIKE 'A%'").children[0]
x = next(select.get_selected_variables())
select.add_type_restriction(x.variable, 'Person')
self.assertEqual(select.as_string(), 'Any X WHERE X name ILIKE "A%", X is Person')
def test_add_new_is_type_restriction_in_on_is_instance_of(self):
tree = self.parse("Any X WHERE X is_instance_of IN(Person, Company), X name ILIKE 'A%'")
select = tree.children[0]
x = next(select.get_selected_variables())
select.add_type_restriction(x.variable, 'Company')
self.assertEqual(tree.as_string(), 'Any X WHERE X name ILIKE "A%", X is Company')
class NodesTest(TestCase):
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 _simpleparse(self, rql):
return self._parse(rql).children[0]
def check_equal_but_not_same(self, tree1, tree2):
#d1 = tree1.__dict__.copy()
#del d1['parent']; del d1['children'] # parent and children are slots now
#d2 = tree2.__dict__.copy()
#del d2['parent']; del d2['children']
self.assertNotEqual(id(tree1), id(tree2))
self.assertTrue(tree1.is_equivalent(tree2))
#self.assertEqual(len(tree1.children), len(tree2.children))
#for i in range(len(tree1.children)):
# self.check_equal_but_not_same(tree1.children[i], tree2.children[i])
# selection tests #########################################################
def test_union_set_limit_1(self):
tree = self._parse("Any X WHERE X is Person")
select = tree.children[0]
self.assertRaises(BadRQLQuery, tree.set_limit, 0)
self.assertRaises(BadRQLQuery, tree.set_limit, -1)
self.assertRaises(BadRQLQuery, tree.set_limit, '1')
tree.save_state()
tree.set_limit(10)
self.assertEqual(select.limit, 10)
self.assertEqual(tree.as_string(), 'Any X LIMIT 10 WHERE X is Person')
tree.recover()
self.assertEqual(select.limit, None)
self.assertEqual(tree.as_string(), 'Any X WHERE X is Person')
def test_union_set_limit_2(self):
# not undoable set_limit since a new root has to be introduced
tree = self._parse("(Any X WHERE X is Person) UNION (Any X WHERE X is Company)")
tree.save_state()
tree.set_limit(10)
self.assertEqual(tree.as_string(), 'Any A LIMIT 10 WITH A BEING ((Any X WHERE X is Person) UNION (Any X WHERE X is Company))')
select = tree.children[0]
self.assertEqual(select.limit, 10)
tree.recover()
self.assertEqual(tree.as_string(), '(Any X WHERE X is Person) UNION (Any X WHERE X is Company)')
def test_union_set_offset_1(self):
tree = self._parse("Any X WHERE X is Person")
select = tree.children[0]
self.assertRaises(BadRQLQuery, tree.set_offset, -1)
self.assertRaises(BadRQLQuery, tree.set_offset, '1')
tree.save_state()
tree.set_offset(10)
self.assertEqual(select.offset, 10)
tree.recover()
self.assertEqual(select.offset, 0)
self.assertEqual(tree.as_string(), 'Any X WHERE X is Person')
def test_union_set_offset_2(self):
# not undoable set_offset since a new root has to be introduced
tree = self._parse("(Any X WHERE X is Person) UNION (Any X WHERE X is Company)")
tree.save_state()
tree.set_offset(10)
select = tree.children[0]
self.assertEqual(tree.as_string(), 'Any A OFFSET 10 WITH A BEING ((Any X WHERE X is Person) UNION (Any X WHERE X is Company))')
self.assertEqual(select.offset, 10)
tree.recover()
self.assertEqual(tree.as_string(), '(Any X WHERE X is Person) UNION (Any X WHERE X is Company)')
def test_union_undo_add_rel(self):
tree = self._parse("Any A WITH A BEING ((Any X WHERE X is Person) UNION (Any X WHERE X is Company))")
tree.save_state()
select = tree.children[0]
var = select.make_variable()
mainvar = select.selection[0].variable
select.add_relation(mainvar, 'name', var)
self.assertEqual(tree.as_string(), 'Any A WHERE A name B WITH A BEING ((Any X WHERE X is Person) UNION (Any X WHERE X is Company))')
tree.recover()
self.assertEqual(tree.as_string(), 'Any A WITH A BEING ((Any X WHERE X is Person) UNION (Any X WHERE X is Company))')
def test_select_set_limit(self):
tree = self._simpleparse("Any X WHERE X is Person")
self.assertEqual(tree.limit, None)
self.assertRaises(BadRQLQuery, tree.set_limit, 0)
self.assertRaises(BadRQLQuery, tree.set_limit, -1)
self.assertRaises(BadRQLQuery, tree.set_limit, '1')
tree.save_state()
tree.set_limit(10)
self.assertEqual(tree.limit, 10)
tree.recover()
self.assertEqual(tree.limit, None)
def test_select_set_offset(self):
tree = self._simpleparse("Any X WHERE X is Person")
self.assertRaises(BadRQLQuery, tree.set_offset, -1)
self.assertRaises(BadRQLQuery, tree.set_offset, '1')
self.assertEqual(tree.offset, 0)
tree.save_state()
tree.set_offset(0)
self.assertEqual(tree.offset, 0)
tree.set_offset(10)
self.assertEqual(tree.offset, 10)
tree.recover()
self.assertEqual(tree.offset, 0)
def test_select_add_sort_var(self):
tree = self._parse('Any X')
tree.save_state()
select = tree.children[0]
select.add_sort_var(select.get_variable('X'))
tree.check_references()
self.assertEqual(tree.as_string(), 'Any X ORDERBY X')
tree.recover()
tree.check_references()
self.assertEqual(tree.as_string(), 'Any X')
def test_select_remove_sort_terms(self):
tree = self._parse('Any X,Y ORDERBY X,Y')
tree.save_state()
select = tree.children[0]
select.remove_sort_terms()
tree.check_references()
self.assertEqual(tree.as_string(), 'Any X,Y')
tree.recover()
tree.check_references()
self.assertEqual(tree.as_string(), 'Any X,Y ORDERBY X,Y')
def test_select_undefine_variable(self):
tree = sparse('Any X,Y ORDERBY X,Y WHERE X work_for Y')
tree.save_state()
select = tree.children[0]
select.undefine_variable(select.defined_vars['Y'])
self.assertCountEqual(select.solutions, [{'X': 'Person'},
{'X': 'Student'}])
tree.check_references()
self.assertEqual(tree.as_string(), 'Any X ORDERBY X')
tree.recover()
tree.check_references()
self.assertEqual(tree.as_string(), 'Any X,Y ORDERBY X,Y WHERE X work_for Y')
self.assertCountEqual(select.solutions,
[{'X': 'Person', 'Y': 'Company'},
{'X': 'Student', 'Y': 'Company'}])
def test_select_set_distinct(self):
tree = self._parse('DISTINCT Any X')
tree.save_state()
select = tree.children[0]
self.assertEqual(select.distinct, True)
tree.save_state()
select.set_distinct(True)
self.assertEqual(select.distinct, True)
tree.recover()
self.assertEqual(select.distinct, True)
select.set_distinct(False)
self.assertEqual(select.distinct, False)
tree.recover()
self.assertEqual(select.distinct, True)
def test_select_add_group_var(self):
tree = self._parse('Any X')
tree.save_state()
select = tree.children[0]
select.add_group_var(select.get_variable('X'))
tree.check_references()
self.assertEqual(tree.as_string(), 'Any X GROUPBY X')
tree.recover()
tree.check_references()
self.assertEqual(tree.as_string(), 'Any X')
def test_select_remove_group_term(self):
tree = self._parse('Any X GROUPBY X')
tree.save_state()
select = tree.children[0]
select.remove_group_term(select.groupby[0])
tree.check_references()
self.assertEqual(tree.as_string(), 'Any X')
tree.recover()
tree.check_references()
self.assertEqual(tree.as_string(), 'Any X GROUPBY X')
def test_select_remove_groups(self):
tree = self._parse('Any X,Y GROUPBY X,Y')
tree.save_state()
select = tree.children[0]
select.remove_groups()
tree.check_references()
self.assertEqual(tree.as_string(), 'Any X,Y')
tree.recover()
tree.check_references()
self.assertEqual(tree.as_string(), 'Any X,Y GROUPBY X,Y')
def test_recover_add_type_restriction_is_in(self):
tree = self._parse('Any X WHERE X is IN(Person, Company), X name ILIKE "A%"')
annotator.annotate(tree) # needed to get typerel index
tree.save_state()
select = tree.children[0]
x = next(select.get_selected_variables())
select.add_type_restriction(x.variable, 'Company')
self.assertEqual(tree.as_string(), 'Any X WHERE X is IN(Company), X name ILIKE "A%"')
tree.recover()
tree.check_references()
self.assertEqual(tree.as_string(), 'Any X WHERE X is IN(Person, Company), X name ILIKE "A%"')
def test_recover_add_type_restriction_is_instance_of(self):
tree = self._parse('Any X WHERE X is_instance_of IN(Person, Company), X name ILIKE "A%"')
annotator.annotate(tree) # needed to get typerel index
tree.save_state()
select = tree.children[0]
x = next(select.get_selected_variables())
select.add_type_restriction(x.variable, 'Company')
self.assertEqual(tree.as_string(), 'Any X WHERE X name ILIKE "A%", X is Company')
tree.recover()
tree.check_references()
self.assertEqual(tree.as_string(), 'Any X WHERE X is_instance_of IN(Person, Company), X name ILIKE "A%"')
def test_select_base_1(self):
tree = self._parse("Any X WHERE X is Person")
self.assertIsInstance(tree, stmts.Union)
select = tree.children[0]
self.assertIsNone(select.limit)
self.assertEqual(select.offset, 0)
self.assertIsInstance(select, stmts.Select)
self.assertEqual(select.distinct, False)
self.assertEqual(len(select.children), 2)
self.assertIs(select.children[0], select.selection[0])
self.assertIs(select.children[1], select.where)
self.assertIsInstance(select.where, nodes.Relation)
def test_select_base_2(self):
tree = self._simpleparse("Any X WHERE X is Person")
self.assertEqual(len(tree.children), 2)
self.assertEqual(tree.distinct, False)
def test_select_distinct(self):
tree = self._simpleparse("DISTINCT Any X WHERE X is Person")
self.assertEqual(len(tree.children), 2)
self.assertEqual(tree.distinct, True)
def test_select_null(self):
tree = self._simpleparse("Any X WHERE X name NULL")
constant = tree.where.children[1].children[0]
self.assertEqual(constant.type, None)
self.assertEqual(constant.value, None)
def test_select_true(self):
tree = self._simpleparse("Any X WHERE X name TRUE")
constant = tree.where.children[1].children[0]
self.assertEqual(constant.type, 'Boolean')
self.assertEqual(constant.value, True)
def test_select_false(self):
tree = self._simpleparse("Any X WHERE X name FALSE")
constant = tree.where.children[1].children[0]
self.assertEqual(constant.type, 'Boolean')
self.assertEqual(constant.value, False)
def test_select_date(self):
tree = self._simpleparse("Any X WHERE X born TODAY")
constant = tree.where.children[1].children[0]
self.assertEqual(constant.type, 'Date')
self.assertEqual(constant.value, 'TODAY')
def test_select_int(self):
tree = self._simpleparse("Any X WHERE X name 1")
constant = tree.where.children[1].children[0]
self.assertEqual(constant.type, 'Int')
self.assertEqual(constant.value, 1)
def test_select_float(self):
tree = self._simpleparse("Any X WHERE X name 1.0")
constant = tree.where.children[1].children[0]
self.assertEqual(constant.type, 'Float')
self.assertEqual(constant.value, 1.0)
def test_select_group(self):
tree = self._simpleparse("Any X GROUPBY N WHERE X is Person, X name N")
self.assertEqual(tree.distinct, False)
self.assertEqual(len(tree.children), 3)
self.assertIsInstance(tree.where, nodes.And)
self.assertIsInstance(tree.groupby[0], nodes.VariableRef)
self.assertEqual(tree.groupby[0].name, 'N')
def test_select_ord_default(self):
tree = self._parse("Any X ORDERBY N WHERE X is Person, X name N")
self.assertEqual(tree.children[0].orderby[0].asc, 1)
def test_select_ord_desc(self):
tree = self._parse("Any X ORDERBY N DESC WHERE X is Person, X name N")
select = tree.children[0]
self.assertEqual(len(select.children), 3)
self.assertIsInstance(select.where, nodes.And)
sort = select.orderby
self.assertIsInstance(sort[0], nodes.SortTerm)
self.assertEqual(sort[0].term.name, 'N')
self.assertEqual(sort[0].asc, 0)
self.assertEqual(select.distinct, False)
def test_select_group_ord_asc(self):
tree = self._parse("Any X GROUPBY N ORDERBY N ASC WHERE X is Person, X name N",
"Any X GROUPBY N ORDERBY N WHERE X is Person, X name N")
select = tree.children[0]
self.assertEqual(len(select.children), 4)
group = select.groupby
self.assertIsInstance(group[0], nodes.VariableRef)
self.assertEqual(group[0].name, 'N')
def test_select_limit_offset(self):
tree = self._parse("Any X LIMIT 10 OFFSET 10 WHERE X name 1.0")
select = tree.children[0]
self.assertEqual(select.limit, 10)
self.assertEqual(select.offset, 10)
def test_exists(self):
tree = self._simpleparse("Any X,N WHERE X is Person, X name N, EXISTS(X work_for Y)")
def test_copy(self):
tree = self._parse("Any X,LOWER(Y) GROUPBY N ORDERBY N WHERE X is Person, X name N, X date >= TODAY")
select = stmts.Select()
restriction = tree.children[0].where
self.check_equal_but_not_same(restriction, restriction.copy(select))
group = tree.children[0].groupby[0]
self.check_equal_but_not_same(group, group.copy(select))
sort = tree.children[0].orderby[0]
self.check_equal_but_not_same(sort, sort.copy(select))
def test_selected_index(self):
tree = self._simpleparse("Any X ORDERBY N DESC WHERE X is Person, X name N")
annotator.annotate(tree)
self.assertEqual(tree.defined_vars['X'].selected_index(), 0)
self.assertEqual(tree.defined_vars['N'].selected_index(), None)
def test_get_variable_indices_1(self):
dummy = self._parse("Any A,B,C")
dummy.children[0].solutions = [{'A': 'String', 'B': 'EUser', 'C': 'EGroup'},
{'A': 'String', 'B': 'Personne', 'C': 'EGroup'},
{'A': 'String', 'B': 'EUser', 'C': 'Societe'}]
self.assertEqual(dummy.get_variable_indices(), set([1, 2]))
def test_get_variable_indices_2(self):
dummy = self._parse("Any A,B WHERE B relation C")
dummy.children[0].solutions = [{'A': 'String', 'B': 'EUser', 'C': 'EGroup'},
{'A': 'String', 'B': 'Personne', 'C': 'EGroup'},
{'A': 'String', 'B': 'EUser', 'C': 'Societe'}]
self.assertEqual(dummy.get_variable_indices(), set([1]))
def test_get_variable_indices_3(self):
dummy = self._parse("(Any X WHERE X is EGroup) UNION (Any C WHERE C is EUser)")
dummy.children[0].solutions = [{'X': 'EGroup'}]
dummy.children[1].solutions = [{'C': 'EUser'}]
self.assertEqual(dummy.get_variable_indices(), set([0]))
def test_get_variable_indices_4(self):
dummy = self._parse("(Any X,XN WHERE X is EGroup, X name XN) UNION (Any C,CL WHERE C is EUser, C login CL)")
dummy.children[0].solutions = [{'X': 'EGroup', 'XN': 'String'}]
dummy.children[1].solutions = [{'C': 'EUser', 'CL': 'String'}]
self.assertEqual(dummy.get_variable_indices(), set([0]))
# insertion tests #########################################################
def test_insert_base_1(self):
tree = self._parse("INSERT Person X")
self.assertIsInstance(tree, stmts.Insert)
self.assertEqual(len(tree.children), 1)
# test specific attributes
self.assertEqual(len(tree.main_relations), 0)
self.assertEqual(len(tree.main_variables), 1)
self.assertEqual(tree.main_variables[0][0], 'Person')
self.assertIsInstance(tree.main_variables[0][1], nodes.VariableRef)
self.assertEqual(tree.main_variables[0][1].name, 'X')
def test_insert_base_2(self):
tree = self._parse('INSERT Person X : X name "bidule"')
# test specific attributes
self.assertEqual(len(tree.main_relations), 1)
self.assertIsInstance(tree.main_relations[0], nodes.Relation)
self.assertEqual(len(tree.main_variables), 1)
self.assertEqual(tree.main_variables[0][0], 'Person')
self.assertIsInstance(tree.main_variables[0][1], nodes.VariableRef)
self.assertEqual(tree.main_variables[0][1].name, 'X')
def test_insert_multi(self):
tree = self._parse('INSERT Person X, Person Y : X name "bidule", Y name "chouette", X friend Y')
# test specific attributes
self.assertEqual(len(tree.main_relations), 3)
for relation in tree.main_relations:
self.assertIsInstance(relation, nodes.Relation)
self.assertEqual(len(tree.main_variables), 2)
self.assertEqual(tree.main_variables[0][0], 'Person')
self.assertIsInstance(tree.main_variables[0][1], nodes.VariableRef)
self.assertEqual(tree.main_variables[0][1].name, 'X')
self.assertEqual(tree.main_variables[1][0], 'Person')
self.assertIsInstance(tree.main_variables[0][1], nodes.VariableRef)
self.assertEqual(tree.main_variables[1][1].name, 'Y')
def test_insert_where(self):
tree = self._parse('INSERT Person X : X name "bidule", X friend Y WHERE Y name "chouette"')
self.assertEqual(len(tree.children), 4)
self.assertIsInstance(tree.where, nodes.Relation)
# test specific attributes
self.assertEqual(len(tree.main_relations), 2)
for relation in tree.main_relations:
self.assertIsInstance(relation, nodes.Relation)
self.assertEqual(len(tree.main_variables), 1)
self.assertEqual(tree.main_variables[0][0], 'Person')
self.assertIsInstance(tree.main_variables[0][1], nodes.VariableRef)
self.assertEqual(tree.main_variables[0][1].name, 'X')
# update tests ############################################################
def test_update_1(self):
tree = self._parse('SET X name "toto" WHERE X is Person, X name "bidule"')
self.assertIsInstance(tree, stmts.Set)
self.assertEqual(len(tree.children), 2)
self.assertIsInstance(tree.where, nodes.And)
# deletion tests #########################################################
def test_delete_1(self):
tree = self._parse('DELETE Person X WHERE X name "toto"')
self.assertIsInstance(tree, stmts.Delete)
self.assertEqual(len(tree.children), 2)
self.assertIsInstance(tree.where, nodes.Relation)
def test_delete_2(self):
tree = self._parse('DELETE X friend Y WHERE X name "toto"')
self.assertIsInstance(tree, stmts.Delete)
self.assertEqual(len(tree.children), 2)
self.assertIsInstance(tree.where, nodes.Relation)
# as_string tests ####################################################
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 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 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 test_get_type_is_in(self):
tree = sparse("Any X WHERE X is IN (Person, Company)")
select = tree.children[0]
self.assertEqual(select.defined_vars['X'].get_type(), 'Any')
# sub-queries tests #######################################################
def test_subq_colalias_compat(self):
tree = sparse('Any X ORDERBY N WHERE X creation_date <NOW WITH X,N BEING ('
'(Any X,N WHERE X firstname N) UNION (Any X,N WHERE X name N, X is Company))')
select = tree.children[0]
select.save_state()
select.remove_sort_term(select.orderby[0])
select.recover()
X = select.get_variable('X')
N = select.get_variable('N')
self.assertEqual(len(X.references()), 3)
self.assertEqual(len(N.references()), 2)
tree.schema = schema
#annotator.annotate(tree)
# XXX how to choose
self.assertEqual(X.get_type(), 'Company')
self.assertEqual(X.get_type({'X': 'Person'}), 'Person')
#self.assertEqual(N.get_type(), 'String')
self.assertEqual(X.get_description(0, lambda x,**k:x), 'Company, Person, Student')
self.assertEqual(N.get_description(0, lambda x,**k:x), 'firstname, name')
self.assertEqual(X.selected_index(), 0)
self.assertEqual(N.selected_index(), None)
self.assertEqual(X.main_relation(), None)
# non regression tests ####################################################
def test_get_description_and_get_type(self):
tree = sparse("Any N,COUNT(X),NOW-D GROUPBY N WHERE X name N, X creation_date D;")
tree.schema = schema
self.assertEqual(tree.get_description(), [['name', 'COUNT(Company, Person, Student)', 'creation_date']])
select = tree.children[0]
self.assertEqual(select.selection[0].get_type(), 'Any')
self.assertEqual(select.selection[1].get_type(), 'Int')
self.assertEqual(select.defined_vars['D'].get_type({'D': 'Datetime'}), 'Datetime')
self.assertEqual(select.selection[2].get_type({'D': 'Datetime'}), 'Interval')
def test_date_arithmetic(self):
minus_expr = sparse("Any D1-D2;").children[0].selection[0]
plus_expr = sparse("Any D1+D2;").children[0].selection[0]
for d1t, d2t in itertools.combinations_with_replacement(['Date', 'Datetime', 'TZDatetime'], 2):
self.assertEqual(minus_expr.get_type({'D1': d1t, 'D2': d2t}), 'Interval')
with self.assertRaises(CoercionError):
plus_expr.get_type({'D1': d1t, 'D2': d2t})
for d1t in ('Date', 'Datetime', 'TZDatetime'):
expected_type = 'Datetime' if d1t == 'Date' else d1t
self.assertEqual(minus_expr.get_type({'D1': d1t, 'D2': 'Interval'}), expected_type)
self.assertEqual(plus_expr.get_type({'D1': d1t, 'D2': 'Interval'}), expected_type)
def test_get_description_simplified(self):
tree = sparse('Any X,R,D WHERE X eid 2, X work_for R, R creation_date D')
self.assertEqual(tree.get_description(), [['work_for', 'work_for_object', 'creation_date']])
helper.simplify(tree)
# Any since const.uid_type is used while solutions have not been computed
self.assertEqual(tree.get_description(), [['Any', 'work_for_object', 'creation_date']])
def test_repr_encoding(self):
tree = parse(u'Any N where NOT N has_text "bid�le"')
repr(tree)
def test_get_description_mainvar_objrel(self):
tree = sparse('Any X,R,D,Y WHERE X work_for R, R creation_date D, Y owned_by X')
self.assertEqual(tree.get_description(0), [['Person', 'work_for', 'creation_date', 'owned_by_object']])
def test_get_description_mainvar_symrel(self):
tree = sparse('Any X,R,D,Y WHERE X work_for R, R creation_date D, Y connait X')
self.assertEqual(tree.get_description(0), [['Person, Student', 'work_for', 'creation_date', 'connait']])
def test_get_description_cast(self):
tree = sparse('Any CAST(String, Y) WHERE X creation_date Y')
select = tree.children[0]
self.assertEqual(select.selection[0].get_type(), 'String')
self.assertEqual(tree.get_description(0), [['String']])
def test_replace_node_select(self):
tree = sparse(u'Any X, MAX(X) WHERE X name "toto tata"')
select = tree.children[0]
funcnode = sparse(u'Any MAX(X)').children[0].selection[0]
select.replace(funcnode, nodes.Constant(1.0, 'Float'))
def test_replace_node_orderby(self):
tree = sparse(u'Any X ORDERBY MAX(X) WHERE X name "toto tata"')
select = tree.children[0]
funcnode = sparse(u'Any X ORDERBY MAX(X)').children[0].orderby[0]
select.replace(funcnode, nodes.Constant(1.0, 'Float'))
def test_replace_node_groupby(self):
tree = sparse(u'Any X GROUPBY X, MAX(X) WHERE X name "toto tata"')
select = tree.children[0]
funcnode = sparse(u'Any MAX(X)').children[0].selection[0]
select.replace(funcnode, nodes.Constant(1.0, 'Float'))
def test_replace_node_having(self):
tree = sparse(u'Any X WHERE X name "toto tata" HAVING MAX(X) > 1')
select = tree.children[0]
funcnode = sparse(u'Any X HAVING MAX(X) > 1').children[0].having[0]
select.replace(funcnode, nodes.Constant(1.0, 'Float'))
def test_undo_node_having(self):
qs = u'Any X WHERE X name N'
tree = sparse(qs)
select = tree.children[0]
select.save_state()
namevar = select.where.relation().children[-1].children[-1].variable
comp = nodes.Comparison('>')
maxf = nodes.Function('MAX')
maxf.append(nodes.VariableRef(namevar))
comp.append(maxf)
comp.append(nodes.Constant(1, 'Int'))
select.set_having([comp])
select.recover()
self.assertEqual(select.as_string(), qs)
def test_undo_node_having_in_mutable(self):
sparse('DELETE Person X WHERE X name N HAVING MAX(X) > 1')
sparse('SET X name "foo" WHERE X is Person HAVING MAX(X) > 1')
class GetNodesFunctionTest(TestCase):
def test_known_values_1(self):
tree = parse('Any X where X name "turlututu"').children[0]
constants = tree.get_nodes(nodes.Constant)
self.assertEqual(len(constants), 1)
self.assertEqual(isinstance(constants[0], nodes.Constant), 1)
self.assertEqual(constants[0].value, 'turlututu')
def test_known_values_2(self):
tree = parse('Any X where X name "turlututu", Y know X, Y name "chapo pointu"').children[0]
varrefs = tree.get_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_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_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'])
if __name__ == '__main__':
unittest_main()