From: Mike Bayer Date: Sun, 12 Jul 2009 14:33:06 +0000 (+0000) Subject: - sqlalchemy.orm.join and sqlalchemy.orm.outerjoin are now X-Git-Tag: rel_0_5_5~2 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=d99c0a9ecc4234c8bd59836bcbec2262d0a249cd;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - 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] --- diff --git a/CHANGES b/CHANGES index 5323c77655..ffe4c41fc3 100644 --- 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(). 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(). 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 diff --git a/lib/sqlalchemy/orm/__init__.py b/lib/sqlalchemy/orm/__init__.py index 6af8dde9ff..a80d17642b 100644 --- a/lib/sqlalchemy/orm/__init__.py +++ b/lib/sqlalchemy/orm/__init__.py @@ -81,11 +81,13 @@ __all__ = ( 'eagerload', 'eagerload_all', 'extension', + 'join', 'lazyload', 'mapper', 'noload', 'object_mapper', 'object_session', + 'outerjoin', 'polymorphic_union', 'reconstructor', 'relation', diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index dee57bbc10..c0eb3b02ad 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -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: diff --git a/test/orm/_fixtures.py b/test/orm/_fixtures.py index 14709ec433..931d8cadf8 100644 --- a/test/orm/_fixtures.py +++ b/test/orm/_fixtures.py @@ -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. diff --git a/test/orm/test_query.py b/test/orm/test_query.py index de1f3be41c..b079e35f22 100644 --- a/test/orm/test_query.py +++ b/test/orm/test_query.py @@ -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"""