]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Repaired missing import in psycopg2._PGNumeric type when
authorMike Bayer <mike_mp@zzzcomputing.com>
Wed, 7 Apr 2010 20:07:55 +0000 (16:07 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 7 Apr 2010 20:07:55 +0000 (16:07 -0400)
unknown numeric is received.

- psycopg2/pg8000 dialects now aware of REAL[], FLOAT[],
DOUBLE_PRECISION[], NUMERIC[] return types without
raising an exception.

- introducing testing.provide_metadata for all these stupid little
create/drop tests

CHANGES
lib/sqlalchemy/dialects/postgresql/pg8000.py
lib/sqlalchemy/dialects/postgresql/psycopg2.py
lib/sqlalchemy/test/testing.py
test/dialect/test_postgresql.py

diff --git a/CHANGES b/CHANGES
index c556ce6c6dfafe4d0b05f4ac8469436c66638596..f027db6475d79194177c44244fdab5b028a280d4 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -109,6 +109,13 @@ CHANGES
     has been changed.  Thanks to Kumar McMillan for the patch.
     [ticket:1071]
     
+  - Repaired missing import in psycopg2._PGNumeric type when 
+    unknown numeric is received.
+
+  - psycopg2/pg8000 dialects now aware of REAL[], FLOAT[], 
+    DOUBLE_PRECISION[], NUMERIC[] return types without
+    raising an exception.
+    
 - oracle
   - Now using cx_oracle output converters so that the
     DBAPI returns natively the kinds of values we prefer:
index a620daac6ab31a0900995ee45bc561ce6cc40277..c822e37a5738bc392258495f4a52ebcd34767064 100644 (file)
@@ -31,18 +31,18 @@ from sqlalchemy.dialects.postgresql.base import PGDialect, \
 class _PGNumeric(sqltypes.Numeric):
     def result_processor(self, dialect, coltype):
         if self.asdecimal:
-            if coltype in (700, 701):
+            if coltype in (700, 701, 1021, 1022):
                 return processors.to_decimal_processor_factory(decimal.Decimal)
-            elif coltype == 1700:
+            elif coltype in (1700, 1231):
                 # pg8000 returns Decimal natively for 1700
                 return None
             else:
                 raise exc.InvalidRequestError("Unknown PG numeric type: %d" % coltype)
         else:
-            if coltype in (700, 701):
+            if coltype in (700, 701, 1021, 1022):
                 # pg8000 returns float natively for 701
                 return None
-            elif coltype == 1700:
+            elif coltype in (1700, 1231):
                 return processors.to_float
             else:
                 raise exc.InvalidRequestError("Unknown PG numeric type: %d" % coltype)
index f21c9a5589052ad1866fa26ba402e3eb11b60e32..45d1bf29e5ddbe32eb6d105f04b9b45c1c1db9f7 100644 (file)
@@ -60,7 +60,7 @@ import re
 import decimal
 import logging
 
-from sqlalchemy import util
+from sqlalchemy import util, exc
 from sqlalchemy import processors
 from sqlalchemy.engine import base, default
 from sqlalchemy.sql import expression
@@ -80,18 +80,18 @@ class _PGNumeric(sqltypes.Numeric):
 
     def result_processor(self, dialect, coltype):
         if self.asdecimal:
-            if coltype in (700, 701):
+            if coltype in (700, 701, 1021, 1022):
                 return processors.to_decimal_processor_factory(decimal.Decimal)
-            elif coltype == 1700:
+            elif coltype in (1700, 1231):
                 # pg8000 returns Decimal natively for 1700
                 return None
             else:
                 raise exc.InvalidRequestError("Unknown PG numeric type: %d" % coltype)
         else:
-            if coltype in (700, 701):
+            if coltype in (700, 701, 1021, 1022):
                 # pg8000 returns float natively for 701
                 return None
-            elif coltype == 1700:
+            elif coltype in (1700, 1231):
                 return processors.to_float
             else:
                 raise exc.InvalidRequestError("Unknown PG numeric type: %d" % coltype)
index 771b8c90fb8c635e4d782765239fa9b29e5f8c37..70ddc7ba207f1834ede2ad7e3f709f088bedf30f 100644 (file)
@@ -546,6 +546,23 @@ def fixture(table, columns, *rows):
                                     for column_values in rows])
     table.append_ddl_listener('after-create', onload)
 
+def provide_metadata(fn):
+    """Provides a bound MetaData object for a single test, 
+    drops it afterwards."""
+    def maybe(*args, **kw):
+        metadata = schema.MetaData(db)
+        context = dict(fn.func_globals)
+        context['metadata'] = metadata
+        # jython bug #1034
+        rebound = types.FunctionType(
+            fn.func_code, context, fn.func_name, fn.func_defaults,
+            fn.func_closure)
+        try:
+            return rebound(*args, **kw)
+        finally:
+            metadata.drop_all()
+    return function_named(maybe, fn.__name__)
+    
 def resolve_artifact_names(fn):
     """Decorator, augment function globals with tables and classes.
 
index fbe62cdec87f5de8c4419fb5d796c2a0cbbc1c9f..bcf8ac95629c597b54583ae4eee7a6d490b073d8 100644 (file)
@@ -228,7 +228,21 @@ class FloatCoercionTest(TablesTest, AssertsExecutionResults):
             ).scalar()
             eq_(round_decimal(ret, 9), result)
     
-    
+    @testing.provide_metadata
+    def test_arrays(self):
+        t1 = Table('t', metadata, 
+            Column('x', postgresql.ARRAY(Float)),
+            Column('y', postgresql.ARRAY(postgresql.REAL)),
+            Column('z', postgresql.ARRAY(postgresql.DOUBLE_PRECISION)),
+            Column('q', postgresql.ARRAY(Numeric))
+        )
+        metadata.create_all()
+        t1.insert().execute(x=[5], y=[5], z=[6], q=[6.4])
+        row = t1.select().execute().first()
+        eq_(
+            row, 
+            ([5], [5], [6], [decimal.Decimal("6.4")])
+        )
         
 class EnumTest(TestBase, AssertsExecutionResults, AssertsCompiledSQL):
     __only_on__ = 'postgresql'
@@ -1311,8 +1325,17 @@ class MiscTest(TestBase, AssertsExecutionResults, AssertsCompiledSQL):
         else:
             exception_cls = eng.dialect.dbapi.ProgrammingError
         assert_raises(exception_cls, eng.execute, "show transaction isolation level")
-
-
+    
+    @testing.only_on('postgresql+psycopg2', 
+                        "this assertion isn't used on others, "
+                        "except pg8000 which circumvents it")
+    def test_numeric_raise(self):
+        stmt = text("select 'hi' as hi", typemap={'hi':Numeric})
+        assert_raises(
+            exc.InvalidRequestError,
+            testing.db.execute, stmt
+        )
+        
 class TimezoneTest(TestBase):
     """Test timezone-aware datetimes.