]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- [bug] Columns in reflected primary key constraint
authorMike Bayer <mike_mp@zzzcomputing.com>
Sun, 23 Sep 2012 17:42:41 +0000 (13:42 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 23 Sep 2012 17:42:41 +0000 (13:42 -0400)
    are now returned in the order in which the constraint
    itself defines them, rather than how the table
    orders them.  Courtesy Gunnlaugur Por Briem.
    [ticket:2531].

CHANGES
lib/sqlalchemy/dialects/postgresql/base.py
test/dialect/test_postgresql.py

diff --git a/CHANGES b/CHANGES
index ee5f368dd1a48b43b0b2a7961f21be2da9de8150..0d421003de614da8176070ef9b4e3bef19adc521 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -161,6 +161,13 @@ CHANGES
     old SQLite versions that don't deliver
     default info as a string.  [ticket:2265]
 
+- postgresql
+  - [bug] Columns in reflected primary key constraint
+    are now returned in the order in which the constraint
+    itself defines them, rather than how the table
+    orders them.  Courtesy Gunnlaugur Þór Briem.
+    [ticket:2531].
+
 - mysql
   - [bug] Updated mysqlconnector interface to use
     updated "client flag" and "charset" APIs,
index 0cfb4dc477c6a8a8946f6bcfa5d94a193c8a860d..4aaa92eeb2a3242b4257895e078372f656eb9c7b 100644 (file)
@@ -1451,20 +1451,33 @@ class PGDialect(default.DefaultDialect):
         table_oid = self.get_table_oid(connection, table_name, schema,
                                        info_cache=kw.get('info_cache'))
 
-        PK_SQL = """
-            SELECT a.attname
+        if self.server_version_info < (8, 4):
+            # unnest() and generate_subscripts() both introduced in
+            # version 8.4
+            PK_SQL = """
+                SELECT a.attname
                 FROM
                     pg_class t
                     join pg_index ix on t.oid = ix.indrelid
                     join pg_attribute a
                         on t.oid=a.attrelid and a.attnum=ANY(ix.indkey)
-          WHERE
-              t.oid = :table_oid and
-              ix.indisprimary = 't'
-          ORDER BY
-            a.attnum
-        """
-        t = sql.text(PK_SQL, typemap={'attname':sqltypes.Unicode})
+                 WHERE
+                  t.oid = :table_oid and ix.indisprimary = 't'
+                ORDER BY a.attnum
+            """
+        else:
+            PK_SQL = """
+                SELECT a.attname
+                FROM pg_attribute a JOIN (
+                    SELECT unnest(ix.indkey) attnum,
+                           generate_subscripts(ix.indkey, 1) ord
+                    FROM pg_index ix
+                    WHERE ix.indrelid = :table_oid AND ix.indisprimary
+                    ) k ON a.attnum=k.attnum
+                WHERE a.attrelid = :table_oid
+                ORDER BY k.ord
+            """
+        t = sql.text(PK_SQL, typemap={'attname': sqltypes.Unicode})
         c = connection.execute(t, table_oid=table_oid)
         primary_keys = [r[0] for r in c.fetchall()]
         return primary_keys
index acfcedc90bbd9d6a788786f7c794defaf1d60e9e..d62a93111fe9efa6f3654fac456bc36d5cdf1f0b 100644 (file)
@@ -1321,6 +1321,21 @@ class DistinctOnTest(fixtures.TestBase, AssertsCompiledSQL):
 class ReflectionTest(fixtures.TestBase):
     __only_on__ = 'postgresql'
 
+    @testing.fails_if(('postgresql', '<', (8, 4)),
+            "newer query is bypassed due to unsupported SQL functions")
+    @testing.provide_metadata
+    def test_reflected_primary_key_order(self):
+        meta1 = self.metadata
+        subject = Table('subject', meta1,
+                        Column('p1', Integer, primary_key=True),
+                        Column('p2', Integer, primary_key=True),
+                        PrimaryKeyConstraint('p2', 'p1')
+                        )
+        meta1.create_all()
+        meta2 = MetaData(testing.db)
+        subject = Table('subject', meta2, autoload=True)
+        eq_(subject.primary_key.columns.keys(), [u'p2', u'p1'])
+
     @testing.provide_metadata
     def test_pg_weirdchar_reflection(self):
         meta1 = self.metadata