]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Added PGUuid and PGBit types to
authorMike Bayer <mike_mp@zzzcomputing.com>
Sun, 1 Mar 2009 20:24:02 +0000 (20:24 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 1 Mar 2009 20:24:02 +0000 (20:24 +0000)
sqlalchemy.databases.postgres. [ticket:1327]

- Refection of unknown PG types won't crash when those
types are specified within a domain.  [ticket:1327]

- executemany() in conjunction with INSERT..RETURNING is documented as undefined by psycopg2.

CHANGES
lib/sqlalchemy/databases/postgres.py
test/dialect/postgres.py

diff --git a/CHANGES b/CHANGES
index f6fc99271b7776a5a2aa333082d3dc4ae789d544..f47e3ebcb8022007500bfd9663915121ed4f0d44 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -89,6 +89,12 @@ CHANGES
 - postgres
     - Index reflection won't fail when an index with 
       multiple expressions is encountered.
+      
+    - Added PGUuid and PGBit types to 
+      sqlalchemy.databases.postgres. [ticket:1327]
+    
+    - Refection of unknown PG types won't crash when those
+      types are specified within a domain.  [ticket:1327]
 
 - mssql
     - Preliminary support for pymssql 1.0.1
index 8caadfaf8b5bfc3e073ea52e1a5bef1ef3d5b639..038a9e8df47aed5e2b53f8a206ae2a95fea4ce39 100644 (file)
@@ -193,6 +193,14 @@ class PGBoolean(sqltypes.Boolean):
     def get_col_spec(self):
         return "BOOLEAN"
 
+class PGBit(sqltypes.TypeEngine):
+    def get_col_spec(self):
+        return "BIT"
+        
+class PGUuid(sqltypes.TypeEngine):
+    def get_col_spec(self):
+        return "UUID"
+    
 class PGArray(sqltypes.MutableType, sqltypes.Concatenable, sqltypes.TypeEngine):
     def __init__(self, item_type, mutable=True):
         if isinstance(item_type, type):
@@ -283,6 +291,8 @@ ischema_names = {
     'real' : PGFloat,
     'inet': PGInet,
     'cidr': PGCidr,
+    'uuid':PGUuid,
+    'bit':PGBit,
     'macaddr': PGMacAddr,
     'double precision' : PGFloat,
     'timestamp' : PGDateTime,
@@ -527,6 +537,7 @@ class PGDialect(default.DefaultDialect):
             elif attype == 'timestamp without time zone':
                 kwargs['timezone'] = False
 
+            coltype = None
             if attype in ischema_names:
                 coltype = ischema_names[attype]
             else:
@@ -540,8 +551,6 @@ class PGDialect(default.DefaultDialect):
                             # It can, however, override the default value, but can't set it to null.
                             default = domain['default']
                         coltype = ischema_names[domain['attype']]
-                else:
-                    coltype = None
 
             if coltype:
                 coltype = coltype(*args, **kwargs)
index 4b1ab91788a04e4f700f10e284cf9427b6081009..3867d1b019406644d3258292c77e44d9efced1a9 100644 (file)
@@ -95,11 +95,15 @@ class ReturningTest(TestBase, AssertsExecutionResults):
 
             self.assertEqual(result.fetchall(), [(1,)])
 
-            # Multiple inserts only return the last row
-            result2 = table.insert(postgres_returning=[table]).execute(
-                 [{'persons': 2, 'full': False}, {'persons': 3, 'full': True}])
-            self.assertEqual(result2.fetchall(), [(3,3,True)])
-
+            @testing.fails_on('postgres', 'Known limitation of psycopg2')
+            def test_executemany():
+                # return value is documented as failing with psycopg2/executemany
+                result2 = table.insert(postgres_returning=[table]).execute(
+                     [{'persons': 2, 'full': False}, {'persons': 3, 'full': True}])
+                self.assertEqual(result2.fetchall(), [(2, 2, False), (3,3,True)])
+            
+            test_executemany()
+            
             result3 = table.insert(postgres_returning=[(table.c.id*2).label('double_id')]).execute({'persons': 4, 'full': False})
             self.assertEqual([dict(row) for row in result3], [{'double_id':8}])
 
@@ -432,6 +436,25 @@ class DomainReflectionTest(TestBase, AssertsExecutionResults):
         self.assertEquals(str(table.columns.answer.server_default.arg), '0', "Reflected default value didn't equal expected value")
         self.assertTrue(table.columns.answer.nullable, "Expected reflected column to be nullable.")
 
+    def test_unknown_types(self):
+        from sqlalchemy.databases import postgres
+
+        ischema_names = postgres.ischema_names
+        postgres.ischema_names = {}
+        try:
+            m2 = MetaData(testing.db)
+            self.assertRaises(exc.SAWarning, Table, "testtable", m2, autoload=True)
+
+            @testing.emits_warning('Did not recognize type')
+            def warns():
+                m3 = MetaData(testing.db)
+                t3 = Table("testtable", m3, autoload=True)
+                assert t3.c.answer.type.__class__ == sa.types.NullType
+
+        finally:
+            postgres.ischema_names = ischema_names
+
+
 class MiscTest(TestBase, AssertsExecutionResults):
     __only_on__ = 'postgres'
 
@@ -878,6 +901,36 @@ class ServerSideCursorsTest(TestBase, AssertsExecutionResults):
         finally:
             test_table.drop(checkfirst=True)
 
+class SpecialTypesTest(TestBase, ComparesTables):
+    """test DDL and reflection of PG-specific types """
+    
+    __only_on__ = 'postgres'
+    __excluded_on__ = (('postgres', '<', (8, 3, 0)),)
+    
+    def setUpAll(self):
+        global metadata, table
+        metadata = MetaData(testing.db)
+        
+        table = Table('sometable', metadata,
+            Column('id', postgres.PGUuid, primary_key=True),
+            Column('flag', postgres.PGBit),
+            Column('addr', postgres.PGInet),
+            Column('addr2', postgres.PGMacAddr),
+            Column('addr3', postgres.PGCidr)
+        )
+        
+        metadata.create_all()
+    
+    def tearDownAll(self):
+        metadata.drop_all()
+    
+    def test_reflection(self):
+        m = MetaData(testing.db)
+        t = Table('sometable', m, autoload=True)
+        
+        self.assert_tables_equal(table, t)
+        
+
 class MatchTest(TestBase, AssertsCompiledSQL):
     __only_on__ = 'postgres'
     __excluded_on__ = (('postgres', '<', (8, 3, 0)),)