diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2010-03-11 17:43:55 +0000 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2010-03-11 17:43:55 +0000 |
| commit | 757bf74ec040e4b98e97f0603858acc9a3066952 (patch) | |
| tree | 7e9afc6f57daacaec8b77a9eefa91c895e08b019 | |
| parent | e45a14e6fc16ce2626a8dfdbf9d24921bf44cc28 (diff) | |
| parent | 19de4da70f714a1918ed1370f9a4ac589f20b7de (diff) | |
| download | sqlalchemy-757bf74ec040e4b98e97f0603858acc9a3066952.tar.gz | |
merged default tip
| -rw-r--r-- | CHANGES | 8 | ||||
| -rw-r--r-- | lib/sqlalchemy/schema.py | 7 | ||||
| -rw-r--r-- | lib/sqlalchemy/sql/util.py | 4 | ||||
| -rw-r--r-- | test/engine/test_metadata.py | 15 | ||||
| -rw-r--r-- | test/sql/test_generative.py | 5 | ||||
| -rw-r--r-- | test/sql/test_selectable.py | 14 |
6 files changed, 49 insertions, 4 deletions
@@ -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 @@ -184,6 +188,10 @@ CHANGES coercing a returned floating point value into a string on its way to Decimal - this allows accuracy to function on SQLite, MySQL. [ticket:1717] + + - the copy() method of Column now copies over uninitialized + "on table attach" events. Helps with the new declarative + "mixin" capability. - engines - Added an optional C extension to speed up the sql layer by diff --git a/lib/sqlalchemy/schema.py b/lib/sqlalchemy/schema.py index 08386059d..8ffb68a4e 100644 --- a/lib/sqlalchemy/schema.py +++ b/lib/sqlalchemy/schema.py @@ -813,7 +813,7 @@ class Column(SchemaItem, expression.ColumnClause): [c.copy(**kw) for c in self.constraints] + \ [c.copy(**kw) for c in self.foreign_keys if not c.constraint] - return Column( + c = Column( name=self.name, type_=self.type, key = self.key, @@ -828,7 +828,10 @@ class Column(SchemaItem, expression.ColumnClause): server_onupdate=self.server_onupdate, *args ) - + if hasattr(self, '_table_events'): + c._table_events = list(self._table_events) + return c + def _make_proxy(self, selectable, name=None): """Create a *proxy* for this column. 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/engine/test_metadata.py b/test/engine/test_metadata.py index 0d2cb7775..3a1a19cd4 100644 --- a/test/engine/test_metadata.py +++ b/test/engine/test_metadata.py @@ -54,7 +54,20 @@ class MetaDataTest(TestBase, ComparesTables): for a1, a2 in zip(col.foreign_keys, c2.foreign_keys): assert a1 is not a2 eq_(a2._colspec, 'bat.blah') - + + def test_uninitialized_column_copy_events(self): + msgs = [] + def write(t, c): + msgs.append("attach %s.%s" % (t.name, c.name)) + c1 = Column('foo', String()) + c1._on_table_attach(write) + m = MetaData() + for i in xrange(3): + cx = c1.copy() + t = Table('foo%d' % i, m, cx) + eq_(msgs, ['attach foo0.foo', 'attach foo1.foo', 'attach foo2.foo']) + + def test_dupe_tables(self): metadata = MetaData() t1 = Table('table1', metadata, Column('col1', Integer, primary_key=True), 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")) |
