--- a/ChangeLog Fri Jun 10 08:03:41 2011 +0200
+++ b/ChangeLog Thu Jul 07 14:05:59 2011 +0200
@@ -2,11 +2,19 @@
=================
--
-* support != operator for non equality
-* support for CAST function
-* support for regexp-based pattern matching using a REGEXP operator
-* may now GROUPBY functions / column number
-* fix parsing of negative float
+ * remove_group_var renamed into remove_group_term and fixed implementation
+
+ * rql annotator add 'having' list into variable's stinfo, and
+ properly update variable graph
+
+ * new undo_modification context manager on select nodes
+
+2011-06-09 -- 0.29.0
+ * support != operator for non equality
+ * support for CAST function
+ * support for regexp-based pattern matching using a REGEXP operator
+ * may now GROUPBY functions / column number
+ * fix parsing of negative float
2011-01-12 -- 0.28.0
* enhance rewrite_shared_optional so one can specify where the new identity
--- a/nodes.py Fri Jun 10 08:03:41 2011 +0200
+++ b/nodes.py Thu Jul 07 14:05:59 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2004-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2004-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of rql.
--- a/parser.g Fri Jun 10 08:03:41 2011 +0200
+++ b/parser.g Thu Jul 07 14:05:59 2011 +0200
@@ -1,7 +1,7 @@
"""yapps input grammar for RQL.
:organization: Logilab
-:copyright: 2003-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
--- a/stcheck.py Fri Jun 10 08:03:41 2011 +0200
+++ b/stcheck.py Thu Jul 07 14:05:59 2011 +0200
@@ -27,7 +27,7 @@
from rql._exceptions import BadRQLQuery
from rql.utils import function_description
from rql.nodes import (Relation, VariableRef, Constant, Not, Exists, Function,
- And, Variable, variable_refs, make_relation)
+ And, Variable, Comparison, variable_refs, make_relation)
from rql.stmts import Union
@@ -521,6 +521,23 @@
for term in node.groupby:
for vref in term.get_nodes(VariableRef):
bloc_simplification(vref.variable, term)
+ try:
+ vargraph = node.vargraph
+ except AttributeError:
+ vargraph = None
+ # XXX node.having is a list of size 1
+ assert len(node.having) == 1
+ for term in node.having[0].get_nodes(Comparison):
+ for vref in term.iget_nodes(VariableRef):
+ vref.variable.stinfo.setdefault('having', []).append(term)
+ if vargraph is not None:
+ lhsvariables = set(vref.name for vref in term.children[0].get_nodes(VariableRef))
+ rhsvariables = set(vref.name for vref in term.children[1].get_nodes(VariableRef))
+ for v1 in lhsvariables:
+ for v2 in rhsvariables:
+ if v1 != v2:
+ vargraph.setdefault(v1, []).append(v2)
+ vargraph.setdefault(v2, []).append(v1)
def rewrite_shared_optional(self, exists, var, identity_rel_scope=None):
"""if variable is shared across multiple scopes, need some tree
--- a/stmts.py Fri Jun 10 08:03:41 2011 +0200
+++ b/stmts.py Thu Jul 07 14:05:59 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2004-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2004-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of rql.
@@ -27,6 +27,7 @@
from warnings import warn
from logilab.common.decorators import cached
+from logilab.common.deprecation import deprecated
from rql import BadRQLQuery, CoercionError, nodes
from rql.base import BaseNode, Node
@@ -47,6 +48,13 @@
raise AssertionError('vref %r is not referenced (%r)' % (vref, vref.stmt))
return True
+class undo_modification(object):
+ def __init__(self, select):
+ self.select = select
+ def __enter__(self):
+ self.select.save_state()
+ def __exit__(self):
+ self.select.recover()
class ScopeNode(BaseNode):
solutions = () # list of possibles solutions for used variables
@@ -354,6 +362,9 @@
def should_register_op(self):
return self.memorizing and not self.undoing
+ def undo_modification(self):
+ return undo_modification(self)
+
def save_state(self):
"""save the current tree"""
self.undo_manager.push_state()
@@ -708,7 +719,7 @@
elif node in self.orderby:
self.remove_sort_term(node)
elif node in self.groupby:
- self.remove_group_var(node)
+ self.remove_group_term(node)
elif node in self.having:
self.having.remove(node)
# XXX selection
@@ -730,7 +741,7 @@
elif isinstance(vref.parent, nodes.SortTerm):
self.remove_sort_term(vref.parent)
elif vref in self.groupby:
- self.remove_group_var(vref)
+ self.remove_group_term(vref)
else: # selected variable
self.remove_selected(vref)
# effective undefine operation
@@ -796,17 +807,19 @@
from rql.undo import AddGroupOperation
self.undo_manager.add_operation(AddGroupOperation(vref))
- def remove_group_var(self, vref):
+ def remove_group_term(self, term):
"""remove the group variable and the group node if necessary"""
if self.should_register_op:
from rql.undo import RemoveGroupOperation
- self.undo_manager.add_operation(RemoveGroupOperation(vref))
- vref.unregister_reference()
- self.groupby.remove(vref)
+ self.undo_manager.add_operation(RemoveGroupOperation(term))
+ for vref in term.iget_nodes(nodes.VariableRef):
+ vref.unregister_reference()
+ self.groupby.remove(term)
+ remove_group_var = deprecated('[rql 0.29] use remove_group_term instead')(remove_group_term)
def remove_groups(self):
for vref in self.groupby[:]:
- self.remove_group_var(vref)
+ self.remove_group_term(vref)
def add_sort_var(self, var, asc=True):
"""add var in 'orderby' constraints
--- a/test/unittest_nodes.py Fri Jun 10 08:03:41 2011 +0200
+++ b/test/unittest_nodes.py Thu Jul 07 14:05:59 2011 +0200
@@ -1,5 +1,5 @@
# -*- coding: iso-8859-1 -*-
-# copyright 2004-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2004-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of rql.
@@ -232,11 +232,11 @@
tree.check_references()
self.assertEqual(tree.as_string(), 'Any X')
- def test_select_remove_group_var(self):
+ def test_select_remove_group_term(self):
tree = self._parse('Any X GROUPBY X')
tree.save_state()
select = tree.children[0]
- select.remove_group_var(select.groupby[0])
+ select.remove_group_term(select.groupby[0])
tree.check_references()
self.assertEqual(tree.as_string(), 'Any X')
tree.recover()
--- a/test/unittest_parser.py Fri Jun 10 08:03:41 2011 +0200
+++ b/test/unittest_parser.py Thu Jul 07 14:05:59 2011 +0200
@@ -1,5 +1,5 @@
# -*- coding: iso-8859-1 -*-
-# copyright 2004-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2004-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of rql.
--- a/undo.py Fri Jun 10 08:03:41 2011 +0200
+++ b/undo.py Thu Jul 07 14:05:59 2011 +0200
@@ -196,7 +196,7 @@
def undo(self, selection):
"""undo the operation on the selection"""
- self.stmt.remove_group_var(self.node)
+ self.stmt.remove_group_term(self.node)
class RemoveGroupOperation(NodeOperation):
"""Defines how to undo 'remove group'."""