]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- sqlalchemy.orm.join and sqlalchemy.orm.outerjoin are now
authorMike Bayer <mike_mp@zzzcomputing.com>
Sun, 12 Jul 2009 14:33:06 +0000 (14:33 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 12 Jul 2009 14:33:06 +0000 (14:33 +0000)
added to __all__ in sqlalchemy.orm.*. [ticket:1463]

- Fixed bug where Query exception raise would fail when
a too-short composite primary key value were passed to
get().  [ticket:1458]

- rearranged CHANGES for 0.5.5 to be somewhat severity based.

- commented on [ticket:1445]

CHANGES
lib/sqlalchemy/orm/__init__.py
lib/sqlalchemy/orm/query.py
test/orm/_fixtures.py
test/orm/test_query.py

diff --git a/CHANGES b/CHANGES
index 5323c77655dcd23947a7d25bad8685ba37aa8afa..ffe4c41fc3d348cd08cfc7631af2deb764f78712 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -12,6 +12,21 @@ CHANGES
       [ticket:970]
 
 - orm
+    - The "foreign_keys" argument of relation() will now propagate
+      automatically to the backref in the same way that primaryjoin
+      and secondaryjoin do.  For the extremely rare use case where
+      the backref of a relation() has intentionally different
+      "foreign_keys" configured, both sides now need to be
+      configured explicity (if they do in fact require this setting,
+      see the next note...).
+
+    - ...the only known (and really, really rare) use case where a
+      different foreign_keys setting was used on the
+      forwards/backwards side, a composite foreign key that
+      partially points to its own columns, has been enhanced such
+      that the fk->itself aspect of the relation won't be used to
+      determine relation direction.
+
     - Session.mapper is now *deprecated*.
 
       Call session.add() if you'd like a free-standing object to be
@@ -20,14 +35,23 @@ CHANGES
       http://www.sqlalchemy.org/trac/wiki/UsageRecipes/SessionAwareMapper
       The method will remain deprecated throughout 0.6.
 
-    - Fixed bug introduced in 0.5.4 whereby Composite types fail
-      when default-holding columns are flushed.
+    - Fixed Query being able to join() from individual columns of a
+      joined-table subclass entity, i.e.  query(SubClass.foo,
+      SubcClass.bar).join(<anything>).  In most cases, an error
+      "Could not find a FROM clause to join from" would be
+      raised. In a few others, the result would be returned in terms
+      of the base class rather than the subclass - so applications
+      which relied on this erroneous result need to be
+      adjusted. [ticket:1431]
 
     - Fixed a bug involving contains_eager(), which would apply
       itself to a secondary (i.e. lazy) load in a particular rare
       case, producing cartesian products.  improved the targeting of
       query.options() on secondary loads overall [ticket:1461].
 
+    - Fixed bug introduced in 0.5.4 whereby Composite types fail
+      when default-holding columns are flushed.
+
     - Fixed another 0.5.4 bug whereby mutable attributes
       (i.e. PickleType) wouldn't be deserialized correctly when the
       whole object was serialized.  [ticket:1426]
@@ -39,33 +63,9 @@ CHANGES
       placed back in a session would not be fully garbage collected
       unless the Session were explicitly closed out.
 
-    - Fixed Query being able to join() from individual columns of a
-      joined-table subclass entity, i.e.  query(SubClass.foo,
-      SubcClass.bar).join(<anything>).  In most cases, an error
-      "Could not find a FROM clause to join from" would be
-      raised. In a few others, the result would be returned in terms
-      of the base class rather than the subclass - so applications
-      which relied on this erroneous result need to be
-      adjusted. [ticket:1431]
-
     - Fixed bug whereby list-based attributes, like pickletype and
       PGArray, failed to be merged() properly.
 
-    - The "foreign_keys" argument of relation() will now propagate
-      automatically to the backref in the same way that primaryjoin
-      and secondaryjoin do.  For the extremely rare use case where
-      the backref of a relation() has intentionally different
-      "foreign_keys" configured, both sides now need to be
-      configured explicity (if they do in fact require this setting,
-      see the next note...).
-
-    - ...the only known (and really, really rare) use case where a
-      different foreign_keys setting was used on the
-      forwards/backwards side, a composite foreign key that
-      partially points to its own columns, has been enhanced such
-      that the fk->itself aspect of the relation won't be used to
-      determine relation direction.
-
     - Repaired non-working attributes.set_committed_value function.
 
     - Trimmed the pickle format for InstanceState which should
@@ -73,6 +73,13 @@ CHANGES
       format should be backwards compatible with that of 0.5.4 and
       previous.
 
+    - sqlalchemy.orm.join and sqlalchemy.orm.outerjoin are now
+      added to __all__ in sqlalchemy.orm.*. [ticket:1463]
+
+    - Fixed bug where Query exception raise would fail when
+      a too-short composite primary key value were passed to
+      get().  [ticket:1458]
+
 - sql
     - Removed an obscure feature of execute() (including connection,
       engine, Session) whereby a bindparam() construct can be sent
index 6af8dde9ff219eb4ec5ea1b64e717f9be5ebc067..a80d17642b7a8c393f25d3511ec227720154c81b 100644 (file)
@@ -81,11 +81,13 @@ __all__ = (
     'eagerload',
     'eagerload_all',
     'extension',
+    'join',
     'lazyload',
     'mapper',
     'noload',
     'object_mapper',
     'object_session',
+    'outerjoin',
     'polymorphic_union',
     'reconstructor',
     'relation',
index dee57bbc102e8d9b8693178c71cf8fcb59330dea..c0eb3b02adf898c54f86a7d2d56671e597a2d27a 100644 (file)
@@ -972,7 +972,8 @@ class Query(object):
             # TODO:
             # this provides one kind of "backwards join"
             # tested in test/orm/query.py.
-            # remove this in 0.6
+            # removal of this has been considered, but maybe not
+            # see [ticket:1445]
             if not clause:
                 if isinstance(onclause, interfaces.PropComparator):
                     clause = onclause.__clause_element__()
@@ -1414,7 +1415,7 @@ class Query(object):
                     params[_get_params[primary_key].key] = ident[i]
                 except IndexError:
                     raise sa_exc.InvalidRequestError("Could not find enough values to formulate primary key for "
-                        "query.get(); primary key columns are %s" % ', '.join("'%s'" % c for c in q.mapper.primary_key))
+                        "query.get(); primary key columns are %s" % ', '.join("'%s'" % c for c in mapper.primary_key))
             q._params = params
 
         if lockmode is not None:
index 14709ec43328709570a3273d112b9e725f0dbe51..931d8cadf87f7a8433dba39c16712727254948e3 100644 (file)
@@ -165,6 +165,18 @@ nodes = fixture_table(
     ('id', 'parent_id', 'data')
 )
 
+composite_pk_table = fixture_table(
+    Table('composite_pk_table', fixture_metadata,
+        Column('i', Integer, primary_key=True),
+        Column('j', Integer, primary_key=True),
+        Column('k', Integer, nullable=False),                    
+    ),
+    ('i', 'j', 'k'),
+    (1, 2, 3),
+    (2, 1, 4),
+    (1, 1, 5),
+    (2, 2,6))
+
 
 def _load_fixtures():
     for table in fixture_metadata.sorted_tables:
@@ -203,6 +215,9 @@ class Dingaling(Base):
 
 class Node(Base):
     pass
+
+class CompositePk(Base):
+    pass
     
 class FixtureTest(_base.MappedTest):
     """A MappedTest pre-configured for fixtures.
index de1f3be41c5fd20c5cf31e2e0ce3f96d15ab7e69..b079e35f220ed382e62851a8b90628f73284814d 100644 (file)
@@ -16,7 +16,8 @@ from test.orm import _fixtures
 from test.orm._fixtures import keywords, addresses, Base, Keyword, FixtureTest, \
            Dingaling, item_keywords, dingalings, User, items,\
            orders, Address, users, nodes, \
-            order_items, Item, Order, Node
+            order_items, Item, Order, Node, \
+            composite_pk_table, CompositePk
 
 from test.orm import _base
 
@@ -53,6 +54,8 @@ class QueryTest(_fixtures.FixtureTest):
             )
         })
 
+        mapper(CompositePk, composite_pk_table)
+
         compile_mappers()
 
 class RowTupleTest(QueryTest):
@@ -78,6 +81,17 @@ class GetTest(QueryTest):
         u2 = s.query(User).get(7)
         assert u is not u2
 
+    def test_get_composite_pk(self):
+        s = create_session()
+        assert s.query(CompositePk).get((100,100)) is None
+        one_two = s.query(CompositePk).get((1,2))
+        assert one_two.i == 1
+        assert one_two.j == 2
+        assert one_two.k == 3
+        q = s.query(CompositePk)
+        assert_raises(sa_exc.InvalidRequestError, q.get, 7)        
+        
+
     def test_no_criterion(self):
         """test that get()/load() does not use preexisting filter/etc. criterion"""