diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-03-31 13:35:05 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-03-31 13:35:05 -0400 |
commit | 45046367f34ee2dadb98024b0f2b05248459f978 (patch) | |
tree | 6c13c76762b1d10eb580eb95a6d4cf7840bfb167 /lib/sqlalchemy/sql/util.py | |
parent | b1fb11dda0454ca9738338e7cc549547c158222b (diff) | |
download | sqlalchemy-45046367f34ee2dadb98024b0f2b05248459f978.tar.gz |
- [bug] Fixed bug in expression annotation
mechanics which could lead to incorrect
rendering of SELECT statements with aliases
and joins, particularly when using
column_property(). [ticket:2453]
Diffstat (limited to 'lib/sqlalchemy/sql/util.py')
-rw-r--r-- | lib/sqlalchemy/sql/util.py | 30 |
1 files changed, 21 insertions, 9 deletions
diff --git a/lib/sqlalchemy/sql/util.py b/lib/sqlalchemy/sql/util.py index 97975441e..8d2b5ecfd 100644 --- a/lib/sqlalchemy/sql/util.py +++ b/lib/sqlalchemy/sql/util.py @@ -404,22 +404,30 @@ for cls in expression.__dict__.values() + [schema.Column, schema.Table]: exec "annotated_classes[cls] = Annotated%s" % (cls.__name__) def _deep_annotate(element, annotations, exclude=None): - """Deep copy the given ClauseElement, annotating each element with the given annotations dictionary. + """Deep copy the given ClauseElement, annotating each element + with the given annotations dictionary. Elements within the exclude collection will be cloned but not annotated. """ + cloned = util.column_dict() + def clone(elem): # check if element is present in the exclude list. # take into account proxying relationships. - if exclude and \ + if elem in cloned: + return cloned[elem] + elif exclude and \ hasattr(elem, 'proxy_set') and \ elem.proxy_set.intersection(exclude): - elem = elem._clone() + newelem = elem._clone() elif annotations != elem._annotations: - elem = elem._annotate(annotations.copy()) - elem._copy_internals(clone=clone) - return elem + newelem = elem._annotate(annotations) + else: + newelem = elem + newelem._copy_internals(clone=clone) + cloned[elem] = newelem + return newelem if element is not None: element = clone(element) @@ -428,10 +436,14 @@ def _deep_annotate(element, annotations, exclude=None): def _deep_deannotate(element): """Deep copy the given element, removing all annotations.""" + cloned = util.column_dict() + def clone(elem): - elem = elem._deannotate() - elem._copy_internals(clone=clone) - return elem + if elem not in cloned: + newelem = elem._deannotate() + newelem._copy_internals(clone=clone) + cloned[elem] = newelem + return cloned[elem] if element is not None: element = clone(element) |