]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- adjusted the literal coercion rules to take the left side's type into account,...
authorMike Bayer <mike_mp@zzzcomputing.com>
Mon, 1 Mar 2010 01:00:12 +0000 (01:00 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 1 Mar 2010 01:00:12 +0000 (01:00 +0000)
compatible with what was found for the right, so that things like oracle CHAR conversions
work.
- oracle dialect specific tests pass again.

CHANGES
lib/sqlalchemy/sql/expression.py
lib/sqlalchemy/types.py
test/sql/test_types.py

diff --git a/CHANGES b/CHANGES
index d7695c40f16677fd76eac43b44b7c82c6d9e29cc..3a1376b32863ee3c47e3a66d8ddb9cdfebe6f84e 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -151,8 +151,10 @@ CHANGES
     "literal" is first derived from the Python type of the 
     literal, assuming standard native Python types + date 
     types, before falling back to that of the known type
-    on the other side of the expression.  Also part
-    of [ticket:1683].
+    on the other side of the expression.  If the 
+    "fallback" type is compatible (i.e. CHAR from String),
+    the literal side will use that.  Also part of 
+    [ticket:1683].
 
   - Made sqlalchemy.sql.expressions.Executable part of public 
     API, used for any expression construct that can be sent to
index f3a1562c557cbb54aaa0e9287e5e1f53c877be6c..1c3961f1f78f462d00857e47927e65b6a6d8eba1 100644 (file)
@@ -2155,6 +2155,8 @@ class _BindParamClause(ColumnElement):
         
         if type_ is None:
             self.type = sqltypes.type_map.get(type(value), _fallback_type or sqltypes.NULLTYPE)
+            if _fallback_type and _fallback_type._type_affinity == self.type._type_affinity:
+                self.type = _fallback_type
         elif isinstance(type_, type):
             self.type = type_()
         else:
index 7f1e38003e258fc651a38b812a09ecdec483eb0a..cdbf7927efb7ae77b5562c8595d73246365b9f92 100644 (file)
@@ -704,7 +704,8 @@ class Unicode(String):
           
         """
         kwargs.setdefault('convert_unicode', True)
-        super(Unicode, self).__init__(length=length, _warn_on_bytestring=True, **kwargs)
+        kwargs.setdefault('_warn_on_bytestring', True)
+        super(Unicode, self).__init__(length=length, **kwargs)
 
 class UnicodeText(Text):
     """An unbounded-length Unicode string.
@@ -732,7 +733,8 @@ class UnicodeText(Text):
 
         """
         kwargs.setdefault('convert_unicode', True)
-        super(UnicodeText, self).__init__(length=length, _warn_on_bytestring=True, **kwargs)
+        kwargs.setdefault('_warn_on_bytestring', True)
+        super(UnicodeText, self).__init__(length=length, **kwargs)
 
 
 class Integer(_DateAffinity, TypeEngine):
@@ -838,7 +840,10 @@ class Numeric(_DateAffinity, TypeEngine):
 #            try:
 #                from fastdec import mpd as Decimal
 #            except ImportError:
-            return processors.to_decimal_processor_factory(_python_Decimal, self.scale)
+            if self.scale is not None:
+                return processors.to_decimal_processor_factory(_python_Decimal, self.scale)
+            else:
+                return processors.to_decimal_processor_factory(_python_Decimal)
         else:
             return None
 
index 29b337eda5ebb995a1480588fd40766517118ced..3ac8baf00464f2c175b74724efbcb5b25327b294 100644 (file)
@@ -4,7 +4,7 @@ import decimal
 import datetime, os, re
 from sqlalchemy import *
 from sqlalchemy import exc, types, util, schema
-from sqlalchemy.sql import operators
+from sqlalchemy.sql import operators, column
 from sqlalchemy.test.testing import eq_
 import sqlalchemy.engine.url as url
 from sqlalchemy.databases import *
@@ -734,8 +734,9 @@ class ExpressionTest(TestBase, AssertsExecutionResults):
         )
 
     def test_bind_adapt(self):
+        # test an untyped bind gets the left side's type
         expr = test_table.c.atimestamp == bindparam("thedate")
-        assert expr.right.type.__class__ == test_table.c.atimestamp.type.__class__
+        eq_(expr.right.type._type_affinity, Date)
 
         eq_(
             testing.db.execute(
@@ -745,13 +746,31 @@ class ExpressionTest(TestBase, AssertsExecutionResults):
         )
 
         expr = test_table.c.avalue == bindparam("somevalue")
-        eq_(expr.right.type.__class__, test_table.c.avalue.type.__class__)
+        eq_(expr.right.type._type_affinity, MyCustomType)
         
         eq_(
             testing.db.execute(test_table.select().where(expr), {"somevalue":25}).fetchall(),
             [(1, 'somedata', datetime.date(2007, 10, 15), 25)]
         )
+    
+    def test_literal_adapt(self):
+        # literals get typed based on the types dictionary, unless compatible
+        # with the left side type
+
+        expr = column('foo', String) == 5
+        eq_(expr.right.type._type_affinity, Integer)
+
+        expr = column('foo', String) == "asdf"
+        eq_(expr.right.type._type_affinity, String)
+
+        expr = column('foo', CHAR) == 5
+        eq_(expr.right.type._type_affinity, Integer)
 
+        expr = column('foo', CHAR) == "asdf"
+        eq_(expr.right.type.__class__, CHAR)
+        
+        
+        
     @testing.fails_on('firebird', 'Data type unknown on the parameter')
     def test_operator_adapt(self):
         """test type-based overloading of operators"""