]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Unary expressions such as DISTINCT propagate their
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 25 Jul 2009 19:34:02 +0000 (19:34 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 25 Jul 2009 19:34:02 +0000 (19:34 +0000)
type handling to result sets, allowing conversions like
unicode and such to take place.  [ticket:1420]

CHANGES
lib/sqlalchemy/sql/compiler.py
lib/sqlalchemy/sql/expression.py
test/sql/test_query.py
test/sql/test_types.py

diff --git a/CHANGES b/CHANGES
index 5234440a0a9c35363b410fbd7bfdef44f3e828fe..fa829286534a84538933485cad86d18cd801a536 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -25,6 +25,11 @@ CHANGES
       the string "field" argument was getting treated as a 
       ClauseElement, causing various errors within more 
       complex SQL transformations.
+      
+    - Unary expressions such as DISTINCT propagate their 
+      type handling to result sets, allowing conversions like
+      unicode and such to take place.  [ticket:1420]
+      
 - ext
    - The collection proxies produced by associationproxy are now
      pickleable.  A user-defined proxy_factory however
index 5140b7f20e0a92cb64e90a080d5aed11f2263040..6af65ec140b36cb729118079bfee8de5e56c8193 100644 (file)
@@ -405,8 +405,8 @@ class DefaultCompiler(engine.Compiled):
         else:
             return text
 
-    def visit_unary(self, unary, **kwargs):
-        s = self.process(unary.element)
+    def visit_unary(self, unary, **kw):
+        s = self.process(unary.element, **kw)
         if unary.operator:
             s = self.operator_string(unary.operator) + " " + s
         if unary.modifier:
index b5eb0eee97c5fee33bc9ab45e2cd334f2a6c004d..0dae6716d4dfacab202a488c78108c7a68670a99 100644 (file)
@@ -400,8 +400,8 @@ def not_(clause):
 
 def distinct(expr):
     """Return a ``DISTINCT`` clause."""
-
-    return _UnaryExpression(expr, operator=operators.distinct_op)
+    expr = _literal_as_binds(expr)
+    return _UnaryExpression(expr, operator=operators.distinct_op, type_=expr.type)
 
 def between(ctest, cleft, cright):
     """Return a ``BETWEEN`` predicate clause.
@@ -1476,8 +1476,7 @@ class _CompareMixin(ColumnOperators):
 
     def distinct(self):
         """Produce a DISTINCT clause, i.e. ``DISTINCT <columnname>``"""
-
-        return _UnaryExpression(self, operator=operators.distinct_op)
+        return _UnaryExpression(self, operator=operators.distinct_op, type_=self.type)
 
     def between(self, cleft, cright):
         """Produce a BETWEEN clause, i.e. ``<column> BETWEEN <cleft> AND <cright>``"""
index c9305b615f058a07e6f4cc2d7cf21034ea81458c..51b933e45857da943873e85e70964a1ba8e41eba 100644 (file)
@@ -469,6 +469,13 @@ class QueryTest(TestBase):
         self.assert_(r['query_users.user_id']) == 1
         self.assert_(r['query_users.user_name']) == "john"
 
+        # unary experssions
+        r = select([users.c.user_name.distinct()]).order_by(users.c.user_name).execute().fetchone()
+        eq_(r[users.c.user_name], 'jack')
+        eq_(r.user_name, 'jack')
+        r.close()
+        
+        
     def test_row_as_args(self):
         users.insert().execute(user_id=1, user_name='john')
         r = users.select(users.c.user_id==1).execute().fetchone()
index 13b6d0954e52c4050835fdc7358c5995324728d5..15799358a7094e1c2ea2882128cea93267624d1a 100644 (file)
@@ -529,6 +529,16 @@ class ExpressionTest(TestBase, AssertsExecutionResults):
         # this one relies upon anonymous labeling to assemble result
         # processing rules on the column.
         assert testing.db.execute(select([expr])).scalar() == -15
+        
+    def test_distinct(self):
+        s = select([distinct(test_table.c.avalue)])
+        eq_(testing.db.execute(s).scalar(), 25)
+
+        s = select([test_table.c.avalue.distinct()])
+        eq_(testing.db.execute(s).scalar(), 25)
+
+        assert distinct(test_table.c.data).type == test_table.c.data.type
+        assert test_table.c.data.distinct().type == test_table.c.data.type
 
 class DateTest(TestBase, AssertsExecutionResults):
     @classmethod