Commits

Mike Bayer  committed 5d1bf1d

- 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]

- rearranged CHANGES for 0.5.5 to be somewhat severity based.

- commented on [ticket:1445]

  • Participants
  • Parent commits 7bb07b5

Comments (0)

Files changed (5)

       [ticket:970]
 
 - orm
-    - Session.mapper is now *deprecated*.
-
-      Call session.add() if you'd like a free-standing object to be
-      part of your session.  Otherwise, a DIY version of
-      Session.mapper is now documented at
-      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 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 another 0.5.4 bug whereby mutable attributes
-      (i.e. PickleType) wouldn't be deserialized correctly when the
-      whole object was serialized.  [ticket:1426]
-
-    - Fixed bug whereby session.is_modified() would raise an
-      exception if any synonyms were in use.
-
-    - Fixed potential memory leak whereby previously pickled objects
-      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
       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
+      part of your session.  Otherwise, a DIY version of
+      Session.mapper is now documented at
+      http://www.sqlalchemy.org/trac/wiki/UsageRecipes/SessionAwareMapper
+      The method will remain deprecated throughout 0.6.
+
+    - 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]
+
+    - Fixed bug whereby session.is_modified() would raise an
+      exception if any synonyms were in use.
+
+    - Fixed potential memory leak whereby previously pickled objects
+      placed back in a session would not be fully garbage collected
+      unless the Session were explicitly closed out.
+
+    - Fixed bug whereby list-based attributes, like pickletype and
+      PGArray, failed to be merged() properly.
+
     - Repaired non-working attributes.set_committed_value function.
 
     - Trimmed the pickle format for InstanceState which should
       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

File lib/sqlalchemy/orm/__init__.py

     'eagerload',
     'eagerload_all',
     'extension',
+    'join',
     'lazyload',
     'mapper',
     'noload',
     'object_mapper',
     'object_session',
+    'outerjoin',
     'polymorphic_union',
     'reconstructor',
     'relation',

File lib/sqlalchemy/orm/query.py

             # 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__()
                     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:

File test/orm/_fixtures.py

     ('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:
 
 class Node(Base):
     pass
+
+class CompositePk(Base):
+    pass
     
 class FixtureTest(_base.MappedTest):
     """A MappedTest pre-configured for fixtures.

File test/orm/test_query.py

 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
 
             )
         })
 
+        mapper(CompositePk, composite_pk_table)
+
         compile_mappers()
 
 class RowTupleTest(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"""