]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Test for EXCLUDE constraint duplicated index
authorMike Bayer <mike_mp@zzzcomputing.com>
Wed, 25 Oct 2017 19:01:55 +0000 (15:01 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 25 Oct 2017 19:02:46 +0000 (15:02 -0400)
An EXCLUDE constraint makes an index just like a UNIQUE does;
get_indexes() will receive this.  Test that this works out the
same way as it does for a UNIQUE.

Change-Id: I02ac7cbbb1ca0d1fcdcdbe9a8b8bd1ffee3e496c
Fixes: #4122
test/dialect/postgresql/test_reflection.py
test/requirements.py

index a1942ab30323451af341b524db0a6812966ccbb6..5c52195d13b425846f32d762f3ecf1df8f19287e 100644 (file)
@@ -13,7 +13,8 @@ from sqlalchemy import Table, Column, MetaData, Integer, String, \
 from sqlalchemy import exc
 import sqlalchemy as sa
 from sqlalchemy.dialects.postgresql import base as postgresql
-from sqlalchemy.dialects.postgresql import ARRAY, INTERVAL
+from sqlalchemy.dialects.postgresql import ARRAY, INTERVAL, TSRANGE
+from sqlalchemy.dialects.postgresql import ExcludeConstraint
 import re
 
 
@@ -971,6 +972,36 @@ class ReflectionTest(fixtures.TestBase):
         self.assert_('uc_a' not in indexes)
         self.assert_('uc_a' in constraints)
 
+    @testing.requires.btree_gist
+    @testing.provide_metadata
+    def test_reflection_with_exclude_constraint(self):
+        m = self.metadata
+        Table(
+            't', m,
+            Column('id', Integer, primary_key=True),
+            Column('period', TSRANGE),
+            ExcludeConstraint(('period', '&&'), name='quarters_period_excl')
+        )
+
+        m.create_all()
+
+        insp = inspect(testing.db)
+
+        # PostgreSQL will create an implicit index for an exclude constraint.
+        # we don't reflect the EXCLUDE yet.
+        eq_(
+            insp.get_indexes('t'),
+            [{'unique': False, 'name': 'quarters_period_excl',
+              'duplicates_constraint': 'quarters_period_excl',
+              'dialect_options': {'postgresql_using': 'gist'},
+              'column_names': ['period']}]
+        )
+
+        # reflection corrects for the dupe
+        reflected = Table('t', MetaData(testing.db), autoload=True)
+
+        eq_(set(reflected.indexes), set())
+
     @testing.provide_metadata
     def test_reflect_unique_index(self):
         insp = inspect(testing.db)
@@ -1026,6 +1057,7 @@ class ReflectionTest(fixtures.TestBase):
         })
 
 
+
 class CustomTypeReflectionTest(fixtures.TestBase):
 
     class CustomType(object):
index e01c686aeedecfb04be64de2a9d6a61e7081c190..dac9494004646f873c63c461a6bd74c1ddec9bfe 100644 (file)
@@ -829,18 +829,23 @@ class DefaultRequirements(SuiteRequirements):
     def duplicate_key_raises_integrity_error(self):
         return fails_on("postgresql+pg8000")
 
-    @property
-    def hstore(self):
-        def check_hstore(config):
+    def _has_pg_extension(self, name):
+        def check(config):
             if not against(config, "postgresql"):
                 return False
-            try:
-                config.db.execute("SELECT 'a=>1,a=>2'::hstore;")
-                return True
-            except Exception:
-                return False
+            count = config.db.scalar(
+                "SELECT count(*) FROM pg_extension "
+                "WHERE extname='%s'" % name)
+            return bool(count)
+        return only_if(check, "needs %s extension" % name)
 
-        return only_if(check_hstore)
+    @property
+    def hstore(self):
+        return self._has_pg_extension("hstore")
+
+    @property
+    def btree_gist(self):
+        return self._has_pg_extension("btree_gist")
 
     @property
     def range_types(self):