summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2010-03-11 12:07:08 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2010-03-11 12:07:08 -0500
commit86df449c2b724341f3d3f322ad71252b287e1f12 (patch)
tree93abff72f69eb43265b586d3bc65b3a71267c6e5
parentea4916001d5023100549d5dcc07ef51657d079fc (diff)
downloadsqlalchemy-86df449c2b724341f3d3f322ad71252b287e1f12.tar.gz
- fixed internal error which would occur if calling has()
or similar complex expression on a single-table inheritance relation(). [ticket:1731]
-rw-r--r--CHANGES4
-rw-r--r--lib/sqlalchemy/sql/util.py4
-rw-r--r--test/sql/test_generative.py5
-rw-r--r--test/sql/test_selectable.py14
4 files changed, 26 insertions, 1 deletions
diff --git a/CHANGES b/CHANGES
index a7457e6d3..fe9f32396 100644
--- a/CHANGES
+++ b/CHANGES
@@ -34,6 +34,10 @@ CHANGES
- session.merge() works with relations that specifically
don't include "merge" in their cascade options - the target
is ignored completely.
+
+ - fixed internal error which would occur if calling has()
+ or similar complex expression on a single-table inheritance
+ relation(). [ticket:1731]
- query.one() no longer applies LIMIT to the query, this to
ensure that it fully counts all object identities present
diff --git a/lib/sqlalchemy/sql/util.py b/lib/sqlalchemy/sql/util.py
index 43673eaec..1b90a457f 100644
--- a/lib/sqlalchemy/sql/util.py
+++ b/lib/sqlalchemy/sql/util.py
@@ -276,7 +276,9 @@ def _deep_annotate(element, annotations, exclude=None):
def clone(elem):
# check if element is present in the exclude list.
# take into account proxying relationships.
- if exclude and elem.proxy_set.intersection(exclude):
+ if exclude and \
+ hasattr(elem, 'proxy_set') and \
+ elem.proxy_set.intersection(exclude):
elem = elem._clone()
elif annotations != elem._annotations:
elem = elem._annotate(annotations.copy())
diff --git a/test/sql/test_generative.py b/test/sql/test_generative.py
index c31a24b93..a6f8c5956 100644
--- a/test/sql/test_generative.py
+++ b/test/sql/test_generative.py
@@ -286,6 +286,11 @@ class ClauseTest(TestBase, AssertsCompiledSQL):
assert u2.compile().params == {'id_param':7}
assert u3.compile().params == {'id_param':10}
+ def test_in(self):
+ expr = t1.c.col1.in_(['foo', 'bar'])
+ expr2 = CloningVisitor().traverse(expr)
+ assert str(expr) == str(expr2)
+
def test_adapt_union(self):
u = union(t1.select().where(t1.c.col1==4), t1.select().where(t1.c.col1==5)).alias()
diff --git a/test/sql/test_selectable.py b/test/sql/test_selectable.py
index f5f61aab1..78455e6d6 100644
--- a/test/sql/test_selectable.py
+++ b/test/sql/test_selectable.py
@@ -549,6 +549,20 @@ class AnnotationsTest(TestBase):
b5 = visitors.cloned_traverse(b3, {}, {'binary':visit_binary})
assert str(b5) == ":bar = table1.col2"
+ def test_annotate_expressions(self):
+ table1 = table('table1', column("col1"), column("col2"))
+
+ for expr, expected in [
+ (table1.c.col1, "table1.col1"),
+ (table1.c.col1 == 5, "table1.col1 = :col1_1"),
+ (table1.c.col1.in_([2,3,4]), "table1.col1 IN (:col1_1, :col1_2, :col1_3)")
+ ]:
+ eq_(str(expr), expected)
+ eq_(str(expr._annotate({})), expected)
+ eq_(str(sql_util._deep_annotate(expr, {})), expected)
+ eq_(str(sql_util._deep_annotate(expr, {}, exclude=[table1.c.col1])), expected)
+
+
def test_deannotate(self):
table1 = table('table1', column("col1"), column("col2"))