]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- the Numeric type raises an *enormous* warning when expected
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 3 Apr 2010 14:58:13 +0000 (10:58 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 3 Apr 2010 14:58:13 +0000 (10:58 -0400)
to convert floats to Decimal from a DBAPI that returns floats.
This includes SQLite, Oracle, Sybase, MS-SQL.
[ticket:1759]

CHANGES
lib/sqlalchemy/dialects/oracle/cx_oracle.py
lib/sqlalchemy/types.py
test/dialect/test_oracle.py
test/sql/test_types.py

diff --git a/CHANGES b/CHANGES
index a7c0ef4d485688240877331fcc4383fa76c568ba..6ad85a17c21c175ed11b4bbbb76e94b3e04d14f7 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -85,6 +85,11 @@ CHANGES
      render inside of column expressions already assigned a label.
      [ticket:1747]
 
+   - the Numeric type raises an *enormous* warning when expected
+     to convert floats to Decimal from a DBAPI that returns floats.
+     This includes SQLite, Oracle, Sybase, MS-SQL.
+     [ticket:1759]
+     
 - postgresql
    - The psycopg2 dialect will log NOTICE messages via the
      "sqlalchemy.dialects.postgresql" logger name. 
index 91af6620bc294878fd7f3ee0401ca64390ab6518..c02f188861d18cab93777de4c1dd55d92f6b4c1a 100644 (file)
@@ -345,6 +345,7 @@ class ReturningResultProxy(base.FullyBufferedResultProxy):
 class OracleDialect_cx_oracle(OracleDialect):
     execution_ctx_cls = OracleExecutionContext_cx_oracle
     statement_compiler = OracleCompiler_cx_oracle
+
     driver = "cx_oracle"
     
     colspecs = colspecs = {
index 16cd57f2682f1366ea51bbd4d3fb957e898f7a65..dba75b36e2a978303d3b230668a0b268fc89f84e 100644 (file)
@@ -939,6 +939,13 @@ class Numeric(_DateAffinity, TypeEngine):
                 # we're a "numeric", DBAPI will give us Decimal directly
                 return None
             else:
+                util.warn("Dialect %s+%s does *not* support Decimal objects natively, "
+                            "and SQLAlchemy must convert from floating point - "
+                            "rounding errors and other issues may occur. "
+                            "Please consider storing Decimal numbers as strings or "
+                            "integers on this platform for lossless storage." % 
+                            (dialect.name, dialect.driver))
+                
                 # we're a "numeric", DBAPI returns floats, convert.
                 if self.scale is not None:
                     return processors.to_decimal_processor_factory(_python_Decimal, self.scale)
@@ -976,7 +983,8 @@ class Float(Numeric):
         :param precision: the numeric precision for use in DDL ``CREATE TABLE``.
         
         :param asdecimal: the same flag as that of :class:`Numeric`, but
-          defaults to ``False``.
+          defaults to ``False``.   Note that setting this flag to ``True``
+          results in floating point conversion.
 
         """
         self.precision = precision
index bcb34b05c7b01515ac8fac77ec4207c31d498465..29014799a6cd71fb7ff4c5f467ace1fd28cb383b 100644 (file)
@@ -34,9 +34,9 @@ create or replace procedure foo(x_in IN number, x_out OUT number, y_out OUT numb
     def test_out_params(self):
         result = testing.db.execute(text("begin foo(:x_in, :x_out, :y_out, :z_out); end;", 
                         bindparams=[
-                                bindparam('x_in', Numeric), 
+                                bindparam('x_in', Float), 
                                 outparam('x_out', Integer), 
-                                outparam('y_out', Numeric), 
+                                outparam('y_out', Float), 
                                 outparam('z_out', String)]), 
                                 x_in=5)
         eq_(
@@ -627,6 +627,7 @@ class TypesTest(TestBase, AssertsCompiledSQL):
         finally:
             metadata.drop_all()
         
+    @testing.emits_warning(r".*does \*not\* support Decimal objects natively")    
     def test_numerics(self):
         m = MetaData(testing.db)
         t1 = Table('t1', m, 
index 089ef727d2c7e9d1e3bcadacf952ec8537b23ef8..764ac7584810b4cdcd8c74de16bdc88866864f05 100644 (file)
@@ -1057,6 +1057,7 @@ class NumericTest(TestBase):
     def teardown(self):
         metadata.drop_all()
         
+    @testing.emits_warning(r".*does \*not\* support Decimal objects natively")    
     def _do_test(self, type_, input_, output, filter_ = None):
         t = Table('t', metadata, Column('x', type_))
         t.create()
@@ -1067,10 +1068,10 @@ class NumericTest(TestBase):
         if filter_:
             result = set(filter_(x) for x in result)
             output = set(filter_(x) for x in output)
-        print result
-        print output
+        #print result
+        #print output
         eq_(result, output)
-        
+    
     def test_numeric_as_decimal(self):
         self._do_test(
             Numeric(precision=8, scale=4),