# HG changeset patch # User sylvain.thenault@logilab.fr # Date 1242630346 -7200 # Mon May 18 09:05:46 2009 +0200 # Node ID f5ddbb4c5bae95fc56eb97bcdc7ea322b755889a # Parent 94259dfefe0e2f47665df4e10af15f12bebc3037 delete-trailing-spaces diff --git a/__init__.py b/__init__.py --- a/__init__.py +++ b/__init__.py @@ -80,7 +80,7 @@ self.annotate(rqlst) rqlst.schema = self._annotator.schema return rqlst - + def annotate(self, rqlst): self._annotator.annotate(rqlst) @@ -97,7 +97,7 @@ debug) finally: self._analyser_lock.release() - + def compute_all_solutions(self, rqlst, uid_func_mapping=None, kwargs=None, debug=False): """compute syntaxe tree solutions with all types restriction (eg @@ -109,8 +109,8 @@ debug) finally: self._itr_analyser_lock.release() - - + + def simplify(self, rqlst): """Simplify `rqlst` by rewriting non-final variables associated to a const node (if annotator say we can...) @@ -161,7 +161,7 @@ else: rhs = copy_uid_node(select, rhs, vconsts) select.groupby[select.groupby.index(vref)] = rhs - rhs.parent = select + rhs.parent = select elif rel is uidrel or rel.is_types_restriction(): # drop this relation rel.parent.remove(rel) @@ -173,10 +173,10 @@ select.stinfo['rewritten'][var.name] = vconsts if select.stinfo['rewritten'] and select.solutions: select.clean_solutions() - + def compare(self, rqlstring1, rqlstring2): """Compare 2 RQL requests. - + Return True if both requests would return the same results. """ from rql.compare import compare_tree @@ -189,9 +189,9 @@ vconsts.append(node) return node - -def parse(rqlstring, print_errors=True): - """Return a syntax tree created from a RQL string.""" + +def parse(rqlstring, print_errors=True): + """Return a syntax tree created from a RQL string.""" from yapps.runtime import print_error, SyntaxError, NoMoreTokens from rql.parser import Hercule, HerculeScanner # make sure rql string ends with a semi-colon diff --git a/nodes.py b/nodes.py --- a/nodes.py +++ b/nodes.py @@ -42,7 +42,7 @@ timedelta: 'Interval', } - + try: from mx.DateTime import DateTimeType, DateTimeDeltaType, today, now KEYWORD_MAP = {'NOW' : now, @@ -65,7 +65,7 @@ if isinstance(var, Variable): return VariableRef(var, noautoref=1) assert isinstance(var, VariableRef) - return var + return var def variable_refs(node): for vref in node.iget_nodes(VariableRef): @@ -76,14 +76,14 @@ class HSMixin(object): """mixin class for classes which may be the lhs or rhs of an expression""" __slots__ = () - + def relation(self): """return the parent relation where self occurs or None""" try: return self.parent.relation() except AttributeError: return None - + def get_description(self): return self.get_type() @@ -105,9 +105,9 @@ class EditableMixIn(object): """mixin class to add edition functionalities to some nodes, eg root nodes (statement) and Exists nodes - """ + """ __slots__ = () - + @property def undo_manager(self): return self.root.undo_manager @@ -133,7 +133,7 @@ from rql.undo import RemoveNodeOperation self.undo_manager.add_operation(RemoveNodeOperation(node)) node.parent.remove(node) - + def add_restriction(self, relation): """add a restriction relation""" r = self.where @@ -149,7 +149,7 @@ from rql.undo import AddNodeOperation self.undo_manager.add_operation(AddNodeOperation(relation)) return relation - + def add_constant_restriction(self, var, rtype, value, ctype, operator='='): """builds a restriction node to express a constant restriction: @@ -168,16 +168,16 @@ value = iter(value).next() return self.add_restriction(make_relation(var, rtype, (value, ctype), Constant, operator)) - - def add_relation(self, lhsvar, rtype, rhsvar): + + def add_relation(self, lhsvar, rtype, rhsvar): """builds a restriction node to express '<var> eid <eid>'""" return self.add_restriction(make_relation(lhsvar, rtype, (rhsvar,), VariableRef)) - def add_eid_restriction(self, var, eid): + def add_eid_restriction(self, var, eid): """builds a restriction node to express '<var> eid <eid>'""" return self.add_constant_restriction(var, 'eid', eid, 'Int') - + def add_type_restriction(self, var, etype): """builds a restriction node to express : variable is etype""" return self.add_constant_restriction(var, 'is', etype, 'etype') @@ -192,62 +192,62 @@ self.set_aliases(aliases) if query is not None: self.set_query(query) - + def set_aliases(self, aliases): self.aliases = aliases for node in aliases: node.parent = self - + def set_query(self, node): self.query = node node.parent = self def copy(self, stmt): return SubQuery([v.copy(stmt) for v in self.aliases], self.query.copy()) - + @property def children(self): return self.aliases + [self.query] - + def as_string(self, encoding=None, kwargs=None): return '%s BEING (%s)' % (','.join(v.name for v in self.aliases), self.query.as_string()) def __repr__(self): return '%s BEING (%s)' % (','.join(repr(v) for v in self.aliases), repr(self.query)) - + class And(BinaryNode): """a logical AND node (binary)""" __slots__ = () - + def as_string(self, encoding=None, kwargs=None): """return the tree as an encoded rql string""" return '%s, %s' % (self.children[0].as_string(encoding, kwargs), self.children[1].as_string(encoding, kwargs)) def __repr__(self): return '%s AND %s' % (repr(self.children[0]), repr(self.children[1])) - + def ored(self, traverse_scope=False, _fromnode=None): return self.parent.ored(traverse_scope, _fromnode or self) - + def neged(self, traverse_scope=False, _fromnode=None): return self.parent.neged(traverse_scope, _fromnode or self) - + class Or(BinaryNode): """a logical OR node (binary)""" __slots__ = () - + def as_string(self, encoding=None, kwargs=None): return '(%s) OR (%s)' % (self.children[0].as_string(encoding, kwargs), self.children[1].as_string(encoding, kwargs)) - + def __repr__(self): return '%s OR %s' % (repr(self.children[0]), repr(self.children[1])) - + def ored(self, traverse_scope=False, _fromnode=None): return self - + def neged(self, traverse_scope=False, _fromnode=None): return self.parent.neged(traverse_scope, _fromnode or self) @@ -255,23 +255,23 @@ class Not(Node): """a logical NOT node (unary)""" __slots__ = () - + def as_string(self, encoding=None, kwargs=None): if isinstance(self.children[0], (Exists, Relation)): return 'NOT %s' % self.children[0].as_string(encoding, kwargs) return 'NOT (%s)' % self.children[0].as_string(encoding, kwargs) - + def __repr__(self, encoding=None, kwargs=None): return 'NOT (%s)' % repr(self.children[0]) - + @property def sqlscope(self): return self - + def ored(self, traverse_scope=False, _fromnode=None): # XXX consider traverse_scope ? return self.parent.ored(traverse_scope, _fromnode or self) - + def neged(self, traverse_scope=False, _fromnode=None, strict=False): return self @@ -294,11 +294,11 @@ self.set_where(restriction) else: self.query = None - + def copy(self, stmt): new = self.query.copy(stmt) return Exists(new) - + @property def children(self): return (self.query,) @@ -307,10 +307,10 @@ assert self.query is None self.query = node node.parent = self - + def is_equivalent(self, other): raise NotImplementedError - + def as_string(self, encoding=None, kwargs=None): content = self.query and self.query.as_string(encoding, kwargs) return 'EXISTS(%s)' % content @@ -321,11 +321,11 @@ def set_where(self, node): self.query = node node.parent = self - + @property def where(self): return self.query - + def replace(self, oldnode, newnode): assert oldnode is self.query self.query = newnode @@ -335,14 +335,14 @@ def scope(self): return self sqlscope = scope - + def ored(self, traverse_scope=False, _fromnode=None): if not traverse_scope: if _fromnode is not None: # stop here return False return self.parent.ored(traverse_scope, self) return self.parent.ored(traverse_scope, _fromnode) - + def neged(self, traverse_scope=False, _fromnode=None, strict=False): if not traverse_scope: if _fromnode is not None: # stop here @@ -352,29 +352,29 @@ return isinstance(self.parent, Not) return self.parent.neged(traverse_scope, _fromnode) - + class Relation(Node): """a RQL relation""" __slots__ = ('r_type', 'optional', '_q_sqltable', '_q_needcast') # XXX cubicweb specific - + def __init__(self, r_type, optional=None): Node.__init__(self) self.r_type = r_type.encode() self.optional = None self.set_optional(optional) - + def initargs(self, stmt): """return list of arguments to give to __init__ to clone this node""" return self.r_type, self.optional - + def is_equivalent(self, other): if not Node.is_equivalent(self, other): return False if self.r_type != other.r_type: return False return True - + def as_string(self, encoding=None, kwargs=None): """return the tree as an encoded rql string""" try: @@ -398,7 +398,7 @@ self.children[1]) except IndexError: return 'Relation(%s)' % self.r_type - + def set_optional(self, optional): assert optional in (None, 'left', 'right') if optional is not None: @@ -406,14 +406,14 @@ self.optional = 'both' else: self.optional = optional - + def relation(self): """return the parent relation where self occurs or None""" return self - + def ored(self, traverse_scope=False, _fromnode=None): return self.parent.ored(traverse_scope, _fromnode or self) - + def neged(self, traverse_scope=False, _fromnode=None, strict=False): if strict: return isinstance(self.parent, Not) @@ -439,7 +439,7 @@ if isinstance(rhs, Comparison): return rhs.operator return '=' - + def get_parts(self): """return the left hand side and the right hand side of this relation """ @@ -462,21 +462,21 @@ root.undo_manager.add_operation(SetOptionalOperation(self, self.optional)) self.optional= value - + class Comparison(HSMixin, Node): """handle comparisons: - <, <=, =, >=, > LIKE and ILIKE operators have a unique children. + <, <=, =, >=, > LIKE and ILIKE operators have a unique children. """ __slots__ = ('operator',) - + def __init__(self, operator, value=None): Node.__init__(self) if operator == '~=': operator = 'ILIKE' elif operator == '=' and isinstance(value, Constant) and \ value.type is None: - operator = 'IS' + operator = 'IS' assert operator in ('<', '<=', '=', '>=', '>', 'ILIKE', 'LIKE', 'IS'), operator self.operator = operator.encode() if value is not None: @@ -490,7 +490,7 @@ if not Node.is_equivalent(self, other): return False return self.operator == other.operator - + def as_string(self, encoding=None, kwargs=None): """return the tree as an encoded rql string""" if len(self.children) == 0: @@ -506,7 +506,7 @@ def __repr__(self): return '%s %s' % (self.operator, ', '.join(repr(c) for c in self.children)) - + class MathExpression(HSMixin, BinaryNode): """Operators plus, minus, multiply, divide.""" @@ -534,7 +534,7 @@ def __repr__(self): return '(%r %s %r)' % (self.children[0], self.operator, self.children[1]) - + def get_type(self, solution=None, kwargs=None): """return the type of object returned by this function if known @@ -558,7 +558,7 @@ if sorted((lhstype, rhstype)) == ['Float', 'Int']: return 'Float' raise CoercionError(key) - + def get_description(self): """if there is a variable in the math expr used as rhs of a relation, return the name of this relation, else return the type of the math @@ -571,7 +571,7 @@ return rtype return self.get_type() - + class Function(HSMixin, Node): """Class used to deal with aggregat functions (sum, min, max, count, avg) and latter upper(), lower() and other RQL transformations functions @@ -615,16 +615,16 @@ def get_description(self): return self.descr().st_description(self) - + def descr(self): """return the type of object returned by this function if known""" return function_description(self.name) - - + + class Constant(HSMixin, LeafNode): """String, Int, TRUE, FALSE, TODAY, NULL...""" __slots__ = ('value', 'type', 'uid', 'uidtype') - + def __init__(self, value, c_type, _uid=False, _uidtype=None): assert c_type in CONSTANT_TYPES, "Error got c_type="+repr(c_type) LeafNode.__init__(self) # don't care about Node attributes @@ -633,7 +633,7 @@ # updated by the annotator/analyzer if necessary self.uid = _uid self.uidtype = _uidtype - + def initargs(self, stmt): """return list of arguments to give to __init__ to clone this node""" return (self.value, self.type, self.uid, self.uidtype) @@ -642,7 +642,7 @@ if not LeafNode.is_equivalent(self, other): return False return self.type == other.type and self.value == other.value - + def as_string(self, encoding=None, kwargs=None): """return the tree as an encoded rql string (an unicode string is returned if encoding is None) @@ -674,7 +674,7 @@ return quote(self.value.encode(encoding)) return uquote(self.value) return repr(self.value) - + def __repr__(self): return self.as_string('utf8') @@ -719,17 +719,17 @@ if not LeafNode.is_equivalent(self, other): return False return self.name == other.name - + def as_string(self, encoding=None, kwargs=None): """return the tree as an encoded rql string""" return self.name - + def __repr__(self): return 'VarRef(%#X) to %r' % (id(self), self.variable) def __cmp__(self, other): return not self.is_equivalent(other) - + def register_reference(self): self.variable.register_reference(self) @@ -741,7 +741,7 @@ def get_description(self): return self.variable.get_description() - + class SortTerm(Node): """a sort term bind a variable to the boolean <asc> @@ -755,7 +755,7 @@ self.asc = asc if copy is None: self.append(variable) - + def initargs(self, stmt): """return list of arguments to give to __init__ to clone this node""" return (None, self.asc, True) @@ -769,23 +769,23 @@ if self.asc: return '%s' % self.term return '%s DESC' % self.term - + def __repr__(self): if self.asc: return '%r ASC' % self.term return '%r DESC' % self.term - + @property - def term(self): + def term(self): return self.children[0] ############################################################################### - + class Referenceable(object): __slots__ = ('name', 'stinfo') - + def __init__(self, name): self.name = name.strip().encode() # used to collect some global information about the syntax tree @@ -797,11 +797,11 @@ def as_string(self, encoding=None, kwargs=None): """return the tree as an encoded rql string""" return self.name - + def register_reference(self, vref): """add a reference to this variable""" self.stinfo['references'].add(vref) - + def unregister_reference(self, vref): """remove a reference to this variable""" try: @@ -839,7 +839,7 @@ # constant node linked to an uid variable if any 'constnode': None, }) - + def get_type(self, solution=None, kwargs=None): """return entity type of this object, 'Any' if not found""" if solution: @@ -855,7 +855,7 @@ except: # CoertionError, AssertionError :( pass return 'Any' - + def get_description(self): """return : * the name of a relation where this variable is used as lhs, @@ -913,7 +913,7 @@ return rel return None - + class ColumnAlias(Referenceable): __slots__ = ('colnum', 'query', '_q_sql', '_q_sqltable') # XXX ginco specific @@ -921,14 +921,14 @@ super(ColumnAlias, self).__init__(alias) self.colnum = int(colnum) self.query = query - + def __repr__(self): return 'alias %s(%#X)' % (self.name, id(self)) @property def schema(self): return self.query.root.schema - + def get_type(self, solution=None, kwargs=None): """return entity type of this object, 'Any' if not found""" vtype = super(ColumnAlias, self).get_type(solution, kwargs) @@ -938,7 +938,7 @@ if vtype != 'Any': return vtype return vtype - + def get_description(self): """return entity type of this object, 'Any' if not found""" vtype = super(ColumnAlias, self).get_description() @@ -952,57 +952,57 @@ # Variable compatibility def init_copy(self, old): pass - + def set_scope(self, scopenode): - pass + pass def get_scope(self): return self.query scope = property(get_scope, set_scope) sqlscope = scope set_sqlscope = set_scope - - + + class Variable(Referenceable): """ a variable definition, should not be directly added to the syntax tree (use VariableRef instead) - + collects information about a variable use in a syntax tree """ __slots__ = ('stmt', '_q_invariant', '_q_sql', '_q_sqltable') # XXX ginco specific - + def __init__(self, name): super(Variable, self).__init__(name) # reference to the selection self.stmt = None - + def __repr__(self): return '%s(%#X)' % (self.name, id(self)) @property def schema(self): return self.stmt.root.schema - + def prepare_annotation(self): super(Variable, self).prepare_annotation() self.stinfo['scope'] = None self.stinfo['sqlscope'] = None - + def _set_scope(self, key, scopenode): if scopenode is self.stmt or self.stinfo[key] is None: self.stinfo[key] = scopenode elif not (self.stinfo[key] is self.stmt or scopenode is self.stinfo[key]): self.stinfo[key] = common_parent(self.stinfo[key], scopenode).scope - + def set_scope(self, scopenode): - self._set_scope('scope', scopenode) + self._set_scope('scope', scopenode) def get_scope(self): return self.stinfo['scope'] scope = property(get_scope, set_scope) - + def set_sqlscope(self, sqlscopenode): - self._set_scope('sqlscope', sqlscopenode) + self._set_scope('sqlscope', sqlscopenode) def get_sqlscope(self): return self.stinfo['sqlscope'] sqlscope = property(get_sqlscope, set_sqlscope) @@ -1011,7 +1011,7 @@ # should copy variable's possibletypes on copy if not self.stinfo.get('possibletypes'): self.stinfo['possibletypes'] = old.stinfo.get('possibletypes') - + def valuable_references(self): """return the number of "valuable" references : references is in selection or in a non type (is) relations diff --git a/stmts.py b/stmts.py --- a/stmts.py +++ b/stmts.py @@ -38,18 +38,18 @@ solutions = () # list of possibles solutions for used variables _varmaker = None # variable names generator, built when necessary where = None # where clause node - + def __init__(self): # dictionnary of defined variables in the original RQL syntax tree self.defined_vars = {} - + def get_selected_variables(self): return self.selected_terms() - + def set_where(self, node): self.where = node node.parent = self - + def copy(self, copy_solutions=True, solutions=None): new = self.__class__() if self.schema is not None: @@ -61,17 +61,17 @@ return new # construction helper methods ############################################# - + def get_etype(self, name): """return the type object for the given entity's type name - + raise BadRQLQuery on unknown type """ return nodes.Constant(name, 'etype') - + def get_variable(self, name): """get a variable instance from its name - + the variable is created if it doesn't exist yet """ try: @@ -91,7 +91,7 @@ while name in self.defined_vars: name = self._varmaker.next() return name - + def make_variable(self): """create a new variable with an unique name for this tree""" var = self.get_variable(self.allocate_varname()) @@ -99,7 +99,7 @@ from rql.undo import MakeVarOperation self.undo_manager.add_operation(MakeVarOperation(var)) return var - + def set_possible_types(self, solutions, kwargs=_MARKER, key='possibletypes'): if key == 'possibletypes': self.solutions = solutions @@ -131,7 +131,7 @@ print repr(self) raise return True - + class Statement(object): """base class for statement nodes""" @@ -139,19 +139,19 @@ # used schema = None # ISchema annotated = False # set by the annotator - + # def __init__(self): # Node.__init__(self) # # syntax tree meta-information # self.stinfo = {} # navigation helper methods ############################################# - + @property def root(self): """return the root node of the tree""" return self - + @property def stmt(self): return self @@ -160,10 +160,10 @@ def scope(self): return self sqlscope = scope - + def ored(self, traverse_scope=False, _fromnode=None): return None - + def neged(self, traverse_scope=False, _fromnode=None, strict=False): return None @@ -205,7 +205,7 @@ self.wrap_selects() self.children[0].set_offset(offset) offset = property(_get_offset, set_offset) - + def _get_limit(self): warn('limit is now a Select node attribute', DeprecationWarning, stacklevel=2) @@ -217,22 +217,22 @@ self.wrap_selects() self.children[0].set_limit(limit) limit = property(_get_limit, set_limit) - - @property + + @property def root(self): """return the root node of the tree""" if self.parent is None: return self return self.parent.root - + def get_description(self): return [c.get_description() for c in self.children] # repr / as_string / copy ################################################# - + def __repr__(self): return '\nUNION\n'.join(repr(select) for select in self.children) - + def as_string(self, encoding=None, kwargs=None): """return the tree as an encoded rql string""" strings = [select.as_string(encoding, kwargs) @@ -240,7 +240,7 @@ if len(strings) == 1: return strings[0] return ' UNION '.join('(%s)' % part for part in strings) - + def copy(self, copy_children=True): new = Union() if self.schema is not None: @@ -262,7 +262,7 @@ for select in self.children: change.update(select.get_variable_variables(values)) return change - + def _locate_subquery(self, col, etype, kwargs): if len(self.children) == 1 and not self.children[0].with_: return self.children[0] @@ -315,7 +315,7 @@ """reverts the tree as it was when save_state() was last called""" self.memorizing -= 1 assert self.memorizing >= 0 - self.undo_manager.recover() + self.undo_manager.recover() def check_references(self): """test function""" @@ -336,7 +336,7 @@ self.undo_manager.add_operation(RemoveSelectOperation(self, select, idx)) self.children.pop(idx) - + class Select(Statement, nodes.EditableMixIn, ScopeNode): """the select node is the base statement of the syntax tree for selection statement, always child of a UNION root. @@ -354,7 +354,7 @@ with_ = () # set by the annotator has_aggregat = False - + def __init__(self): Statement.__init__(self) ScopeNode.__init__(self) @@ -364,11 +364,11 @@ # syntax tree meta-information self.stinfo = {'rewritten': {}} - @property + @property def root(self): """return the root node of the tree""" return self.parent - + def get_description(self): """return the list of types or relations (if not found) associated to selected variables @@ -397,10 +397,10 @@ return children # repr / as_string / copy ################################################# - + def __repr__(self): return self.as_string(userepr=True) - + def as_string(self, encoding=None, kwargs=None, userepr=False): """return the tree as an encoded rql string""" if userepr: @@ -429,7 +429,7 @@ if self.distinct: return 'DISTINCT Any ' + ' '.join(s) return 'Any ' + ' '.join(s) - + def copy(self, copy_solutions=True, solutions=None): new = ScopeNode.copy(self, copy_solutions, solutions) if self.with_: @@ -449,9 +449,9 @@ new.offset = self.offset new.vargraph = self.vargraph return new - + # select specific methods ################################################# - + def set_possible_types(self, solutions, kwargs=_MARKER, key='possibletypes'): super(Select, self).set_possible_types(solutions, kwargs, key) for ca in self.aliases.itervalues(): @@ -470,7 +470,7 @@ ca.query.remove_select(stmt) else: stmt.set_possible_types(sols) - + def set_statement_type(self, etype): """set the statement type for this selection this method must be called last (i.e. once selected variables has been @@ -481,14 +481,14 @@ if etype != 'Any': for var in self.get_selected_variables(): self.add_type_restriction(var.variable, etype) - + def set_distinct(self, value): """mark DISTINCT query""" if self.should_register_op and value != self.distinct: from rql.undo import SetDistinctOperation self.undo_manager.add_operation(SetDistinctOperation(self.distinct, self)) self.distinct = value - + def set_limit(self, limit): if limit is not None and (not isinstance(limit, (int, long)) or limit <= 0): raise BadRQLQuery('bad limit %s' % limit) @@ -504,7 +504,7 @@ from rql.undo import SetOffsetOperation self.undo_manager.add_operation(SetOffsetOperation(self.offset, self)) self.offset = offset - + def set_orderby(self, terms): self.orderby = terms for node in terms: @@ -519,12 +519,12 @@ self.having = terms for node in terms: node.parent = self - + def set_with(self, terms, check=True): self.with_ = [] for node in terms: self.add_subquery(node, check) - + def add_subquery(self, node, check=True): assert node.query if not isinstance(self.with_, list): @@ -540,16 +540,16 @@ raise BadRQLQuery('Duplicated alias %s' % alias) ca = self.get_variable(alias, i) ca.query = node.query - + def remove_subquery(self, node): self.with_.remove(node) node.parent = None for i, alias in enumerate(node.aliases): del self.aliases[alias.name] - + def get_variable(self, name, colnum=None): """get a variable instance from its name - + the variable is created if it doesn't exist yet """ if name in self.aliases: @@ -564,7 +564,7 @@ vref.variable = calias return self.aliases[name] return super(Select, self).get_variable(name) - + def clean_solutions(self, solutions=None): """when a rqlst has been extracted from another, this method returns solutions which make sense for this sub syntax tree @@ -599,9 +599,9 @@ elif _values[vname] != etype: change.add(vname) return change - + # quick accessors ######################################################### - + def get_selected_variables(self): """returns all selected variables, including those used in aggregate functions @@ -611,7 +611,7 @@ yield node # construction helper methods ############################################# - + def save_state(self): """save the current tree""" self.parent.save_state() @@ -625,7 +625,7 @@ raise BadRQLQuery('Entity type are not allowed in selection') term.parent = self self.selection.append(term) - + def replace(self, oldnode, newnode): assert oldnode is self.where self.where = newnode @@ -637,7 +637,7 @@ # i = self.selection.index(oldnode) # self.selection.pop(i) # self.selection.insert(i, newnode) - + def remove(self, node): if node is self.where: self.where = None @@ -648,7 +648,7 @@ else: raise Exception('duh XXX') node.parent = None - + def undefine_variable(self, var): """undefine the given variable and remove all relations where it appears""" if hasattr(var, 'variable'): @@ -736,7 +736,7 @@ def remove_groups(self): for vref in self.groupby[:]: self.remove_group_var(vref) - + def add_sort_var(self, var, asc=True): """add var in 'orderby' constraints asc is a boolean indicating the sort order (ascendent or descendent) @@ -745,7 +745,7 @@ vref.register_reference() term = nodes.SortTerm(vref, asc) self.add_sort_term(term) - + def add_sort_term(self, term, index=None): if not self.orderby: self.orderby = [] @@ -767,7 +767,7 @@ if self.orderby: for term in self.orderby[:]: self.remove_sort_term(term) - + def remove_sort_term(self, term): """remove a sort term and the sort node if necessary""" if self.should_register_op: @@ -786,12 +786,12 @@ selection.append(vref) self.selection = selection - + class Delete(Statement, ScopeNode): """the Delete node is the root of the syntax tree for deletion statement """ TYPE = 'delete' - + def __init__(self): Statement.__init__(self) ScopeNode.__init__(self) @@ -809,7 +809,7 @@ @property def selection(self): return [vref for et, vref in self.main_variables] - + def add_main_variable(self, etype, vref): """add a variable to the list of deleted variables""" #if etype == 'Any': @@ -824,7 +824,7 @@ assert isinstance(relation.children[1].children[0], nodes.VariableRef) relation.parent = self self.main_relations.append( relation ) - + # repr / as_string / copy ################################################# def __repr__(self): @@ -850,7 +850,7 @@ if self.main_variables: result.append(',') result.append(', '.join([rel.as_string(encoding, kwargs) - for rel in self.main_relations])) + for rel in self.main_relations])) if self.where is not None: result.append('WHERE ' + self.where.as_string(encoding, kwargs)) return ' '.join(result) @@ -871,7 +871,7 @@ """the Insert node is the root of the syntax tree for insertion statement """ TYPE = 'insert' - + def __init__(self): Statement.__init__(self) ScopeNode.__init__(self) @@ -890,7 +890,7 @@ @property def selection(self): return [vref for et, vref in self.main_variables] - + def add_main_variable(self, etype, vref): """add a variable to the list of inserted variables""" if etype == 'Any': @@ -898,7 +898,7 @@ self.main_variables.append( (etype.encode(), vref) ) vref.parent = self self.inserted_variables[vref.variable] = 1 - + def add_main_relation(self, relation): """add a relation to the list of inserted relations""" var = relation.children[0].variable @@ -910,7 +910,7 @@ raise BadRQLQuery(msg % (var, var)) relation.parent = self self.main_relations.append( relation ) - + # repr / as_string / copy ################################################# def __repr__(self): @@ -948,7 +948,7 @@ new.set_where(self.where.copy(new)) return new - + class Set(Statement, ScopeNode): """the Set node is the root of the syntax tree for update statement """ @@ -969,7 +969,7 @@ @property def selection(self): return [] - + def add_main_relation(self, relation): """add a relation to the list of modified relations""" relation.parent = self