]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- [feature] Added the ability to query for
authorMike Bayer <mike_mp@zzzcomputing.com>
Sun, 12 Feb 2012 23:25:19 +0000 (18:25 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 12 Feb 2012 23:25:19 +0000 (18:25 -0500)
Table-bound column names when using
query(sometable).filter_by(colname=value).
[ticket:2400]

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

diff --git a/CHANGES b/CHANGES
index 49488c601b649accd9c59c218a69c1d40bbe7c4d..c954c2de62d4c6a242095244ec1681fddf5c1e27 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,11 @@ CHANGES
 0.7.6
 =====
 - orm
+  - [feature] Added the ability to query for
+    Table-bound column names when using 
+    query(sometable).filter_by(colname=value).  
+    [ticket:2400]
+
   - [bug] Improved the "declarative reflection" 
     example to support single-table inheritance,
     multiple calls to prepare(), tables that
index 9508cb5321eb504990c8f738eb181b5605897dd4..a00d4078a0b1da7620965acbbdcabb3b71ee00d5 100644 (file)
@@ -276,6 +276,7 @@ class Query(object):
         return self._select_from_entity or \
             self._entity_zero().entity_zero
 
+
     @property
     def _mapper_entities(self):
         # TODO: this is wrong, its hardcoded to "primary entity" when
@@ -3086,8 +3087,9 @@ class _MapperEntity(_QueryEntity):
 class _ColumnEntity(_QueryEntity):
     """Column/expression based entity."""
 
-    def __init__(self, query, column):
+    def __init__(self, query, column, namespace=None):
         self.expr = column
+        self.namespace = namespace
 
         if isinstance(column, basestring):
             column = sql.literal_column(column)
@@ -3106,7 +3108,7 @@ class _ColumnEntity(_QueryEntity):
             for c in column._select_iterable:
                 if c is column:
                     break
-                _ColumnEntity(query, c)
+                _ColumnEntity(query, c, namespace=column)
 
             if c is not column:
                 return
@@ -3147,12 +3149,14 @@ class _ColumnEntity(_QueryEntity):
 
         if self.entities:
             self.entity_zero = list(self.entities)[0]
+        elif self.namespace is not None:
+            self.entity_zero = self.namespace
         else:
             self.entity_zero = None
 
     @property
     def entity_zero_or_selectable(self):
-        if self.entity_zero:
+        if self.entity_zero is not None:
             return self.entity_zero
         elif self.actual_froms:
             return list(self.actual_froms)[0]
index 0cd5b059486be9c720cdd468f1aa88f689594066..6ac03d95a96703eca1d827101a6f3fc0210c0cb5 100644 (file)
@@ -557,15 +557,20 @@ def _entity_descriptor(entity, key):
     attribute.
 
     """
-    if not isinstance(entity, (AliasedClass, type)):
-        entity = entity.class_
+    if isinstance(entity, expression.FromClause):
+        description = entity
+        entity = entity.c
+    elif not isinstance(entity, (AliasedClass, type)):
+        description = entity = entity.class_
+    else:
+        description = entity
 
     try:
         return getattr(entity, key)
     except AttributeError:
         raise sa_exc.InvalidRequestError(
                     "Entity '%s' has no property '%s'" % 
-                    (entity, key)
+                    (description, key)
                 )
 
 def _orm_columns(entity):
index 24974ae7e3f22fb2ba8388923df543e157c7d876..451d61a678df336a67990c020cafb01e839dc59a 100644 (file)
@@ -1155,6 +1155,32 @@ class FilterTest(QueryTest, AssertsCompiledSQL):
         assert [User(name='chuck')] == sess.query(User).filter_by(addresses = None).all()
         assert [User(name='chuck')] == sess.query(User).filter_by(addresses = null()).all()
 
+    def test_filter_by_tables(self):
+        users = self.tables.users
+        addresses = self.tables.addresses
+        sess = create_session()
+        self.assert_compile(
+            sess.query(users).\
+                    filter_by(name='ed').\
+                    join(addresses, users.c.id==addresses.c.user_id).\
+                    filter_by(email_address='ed@ed.com'),
+            "SELECT users.id AS users_id, users.name AS users_name "
+            "FROM users JOIN addresses ON users.id = addresses.user_id "
+            "WHERE users.name = :name_1 AND "
+            "addresses.email_address = :email_address_1",
+            checkparams={u'email_address_1': 'ed@ed.com', u'name_1': 'ed'}
+        )
+
+    def test_filter_by_no_property(self):
+        addresses = self.tables.addresses
+        sess = create_session()
+        assert_raises_message(
+            sa.exc.InvalidRequestError,
+            "Entity 'addresses' has no property 'name'",
+            sess.query(addresses).\
+                    filter_by, name='ed'
+        )
+
     def test_none_comparison(self):
         Order, User, Address = (self.classes.Order,
                                 self.classes.User,