- the functionality of query.with_polymorphic() has
been added to mapper() as a configuration option.
+
It's set via several forms:
with_polymorphic='*'
- with_polymorphic=(mappers, selectable)
with_polymorphic=[mappers]
+ with_polymorphic=('*', selectable)
+ with_polymorphic=([mappers], selectable)
+
+ This controls the default polymorphic loading strategy
+ for inherited mappers. When a selectable is not given,
+ outer joins are created for all joined-table inheriting
+ mappers requested. Note that the auto-create of joins
+ is not compatible with concrete table inheritance.
- The existing select_table flag to mapper() is now
+ The existing select_table flag on mapper() is now
deprecated and is synonymous with
with_polymorphic('*', select_table). Note that the
underlying "guts" of select_table have been
completely removed and replaced with the newer,
- more flexible approach.
-
+ more flexible approach.
+
+ The new approach also automatically allows eager loads
+ to work for subclasses, if they are present, for
+ example
+ sess.query(Company).options(
+ eagerload_all(
+ [Company.employees.of_type(Engineer), 'machines']
+ ))
+ to load Company objects, their employees, and the
+ 'machines' collection of employees who happen to be
+ Engineers. A "with_polymorphic" Query option should be
+ introduced soon as well which would allow per-Query
+ control of with_polymorphic() on relations.
+
+ - added two "experimental" features to Query,
+ "experimental" in that their specific name/behavior
+ is not carved in stone just yet: _values() and
+ _from_self(). We'd like feedback on these.
+
+ - _values(*columns) is given a list of column
+ expressions, and returns a new Query that only
+ returns those columns. When evaluated, the return
+ value is a list of tuples just like when using
+ add_column() or add_entity(), the only difference is
+ that "entity zero", i.e. the mapped class, is not
+ included in the results. This means it finally makes
+ sense to use group_by() and having() on Query, which
+ have been sitting around uselessly until now.
+
+ A future change to this method may include that its
+ ability to join, filter and allow other options not
+ related to a "resultset" are removed, so the feedback
+ we're looking for is how people want to use
+ _values()...i.e. at the very end, or do people prefer
+ to continue generating after it's called.
+
+ - _from_self() compiles the SELECT statement for the
+ Query (minus any eager loaders), and returns a new
+ Query that selects from that SELECT. So basically you
+ can query from a Query without needing to extract the
+ SELECT statement manually. This gives meaning to
+ operations like query[3:5]._from_self().filter(some
+ criterion). There's not much controversial here
+ except that you can quickly create highly nested
+ queries that are less efficient, and we want feedback
+ on the naming choice.
+
- query.order_by() and query.group_by() will accept
multiple arguments using *args (like select()
already does).
# o2m
self.assertEquals([User(id=10)], sess.query(User).filter(User.addresses==None).all())
self.assertEquals([User(id=7),User(id=8),User(id=9)], sess.query(User).filter(User.addresses!=None).all())
+
+class FromSelfTest(QueryTest):
+ def test_filter(self):
+
+ assert [User(id=8), User(id=9)] == create_session().query(User).filter(User.id.in_([8,9]))._from_self().all()
+
+ assert [User(id=8), User(id=9)] == create_session().query(User)[1:3]._from_self().all()
+ assert [User(id=8)] == list(create_session().query(User).filter(User.id.in_([8,9]))._from_self()[0:1])
+
+ def test_join(self):
+ assert [
+ (User(id=8), Address(id=2)),
+ (User(id=8), Address(id=3)),
+ (User(id=8), Address(id=4)),
+ (User(id=9), Address(id=5))
+ ] == create_session().query(User).filter(User.id.in_([8,9]))._from_self().join('addresses').add_entity(Address).all()
class AggregateTest(QueryTest):
def test_sum(self):