]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- added _from_self()
authorMike Bayer <mike_mp@zzzcomputing.com>
Sun, 30 Mar 2008 18:05:33 +0000 (18:05 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 30 Mar 2008 18:05:33 +0000 (18:05 +0000)
- changelog authoring

CHANGES
lib/sqlalchemy/orm/query.py
test/orm/query.py

diff --git a/CHANGES b/CHANGES
index 5dea65f02b14364a3f9e8547a05a610cf99d4474..3ffa58203887bbaff67dce015e7db61ff1433015 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -13,18 +13,72 @@ CHANGES
 
     - 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).
index 1d4b24e0c58a7108fcbefc58123986561986355c..9751cc9ba28a18f018e5217dcfe6309f39368147 100644 (file)
@@ -360,7 +360,18 @@ class Query(object):
 
         q._entities = q._entities + [_MapperEntity(mapper=entity, alias=alias, id=id)]
         return q
-
+    
+    def _from_self(self):
+        """return a Query that selects from this Query's SELECT statement.
+        
+        The API for this method hasn't been decided yet and is subject to change.
+        """
+        
+        q = self._clone()
+        q._eager_loaders = util.Set()
+        fromclause = q.compile()
+        return Query(self.mapper, self.session).select_from(fromclause)
+        
     def _values(self, *columns):
         """Turn this query into a 'columns only' query.
         
index a4dbb938d0a6251f061861a0e3c6f42c5d1e8ef3..b985202b4c3fe423d330959ed7e319a301eb09ac 100644 (file)
@@ -408,6 +408,22 @@ class FilterTest(QueryTest):
         # 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):