diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2008-03-29 00:00:49 +0000 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2008-03-29 00:00:49 +0000 |
| commit | c4955c05a3ab40d53c83982da612e746c662640d (patch) | |
| tree | c979c566711917679c9fa5d31b6dbcdb1c76eb34 /lib/sqlalchemy/sql/visitors.py | |
| parent | 30020880d90ee2f983b8e6bfb1624349209dd8b0 (diff) | |
| download | sqlalchemy-c4955c05a3ab40d53c83982da612e746c662640d.tar.gz | |
- merged with_polymorphic branch, which was merged with query_columns branch
- removes everything to do with select_table, which remains as a keyword argument synonymous with
with_polymorphic=('*', select_table).
- all "polymorphic" selectables find their way to Query by way of _set_select_from() now, so that
all joins/aliasing/eager loads/etc. is handled consistently. Mapper has methods for producing
polymorphic selectables so that Query and eagerloaders alike can get to them.
- row aliasing simplified, so that they don't need to nest. they only need the source selectable
and adapt to whatever incoming columns they get.
- Query is more egalitarian about mappers/columns now. Still has a strong sense of "entity zero",
but also introduces new unpublished/experimental _values() method which sets up a columns-only query.
- Query.order_by() and Query.group_by() take *args now (also still take a list, will likely deprecate
in 0.5). May want to do this for select() as well.
- the existing "check for False discriminiator" "fix" was not working completely, added coverage
- orphan detection was broken when the target object was a subclass of the mapper with the orphaned
relation, fixed that too.
Diffstat (limited to 'lib/sqlalchemy/sql/visitors.py')
| -rw-r--r-- | lib/sqlalchemy/sql/visitors.py | 37 |
1 files changed, 12 insertions, 25 deletions
diff --git a/lib/sqlalchemy/sql/visitors.py b/lib/sqlalchemy/sql/visitors.py index 09d5a0982..7eccc9b89 100644 --- a/lib/sqlalchemy/sql/visitors.py +++ b/lib/sqlalchemy/sql/visitors.py @@ -37,17 +37,17 @@ class ClauseVisitor(object): traverse_chained = traverse_single def iterate(self, obj): - """traverse the given expression structure, and return an iterator of all elements.""" + """traverse the given expression structure, returning an iterator of all elements.""" stack = [obj] - traversal = [] - while len(stack) > 0: + traversal = util.deque() + while stack: t = stack.pop() - yield t - traversal.insert(0, t) + traversal.appendleft(t) for c in t.get_children(**self.__traverse_options__): stack.append(c) - + return iter(traversal) + def traverse(self, obj, clone=False): """traverse and visit the given expression structure. @@ -119,32 +119,19 @@ class ClauseVisitor(object): def clone(element): return self._clone_element(element, stop_on, cloned) elem._copy_internals(clone=clone) - - for v in self._iterate_visitors: - meth = getattr(v, "visit_%s" % elem.__visit_name__, None) - if meth: - meth(elem) + + self.traverse_single(elem) for e in elem.get_children(**self.__traverse_options__): if e not in stop_on: self._cloned_traversal_impl(e, stop_on, cloned) return elem - + def _non_cloned_traversal(self, obj): """a non-recursive, non-cloning traversal.""" - - stack = [obj] - traversal = [] - while len(stack) > 0: - t = stack.pop() - traversal.insert(0, t) - for c in t.get_children(**self.__traverse_options__): - stack.append(c) - for target in traversal: - for v in self._iterate_visitors: - meth = getattr(v, "visit_%s" % target.__visit_name__, None) - if meth: - meth(target) + + for target in self.iterate(obj): + self.traverse_single(target) return obj def _iterate_visitors(self): |
