]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Render ARRAY index embedded between type and COLLATE
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 8 Jun 2017 16:55:23 +0000 (12:55 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 8 Jun 2017 21:07:50 +0000 (17:07 -0400)
Fixed bug where using :class:`.ARRAY` with a string type that
features a collation would fail to produce the correct syntax
within CREATE TABLE.

The "COLLATE" must appear to the right of the array dimensions,
so we are using regexp substitution to insert the brackets in the
appropriate place.  A more heavyweight solution would be that datatypes
know how to split up their base type vs. modifiers, but as this is
so specific to Postgresql ARRAY it's better to handle these cases
more locally.

Change-Id: I394c3c673eb60689e51b5301e51651972cfdb4c0
Fixes: #4006
(cherry picked from commit ec422fb70e0044ed42dcfda5fb1a7a65db322cf1)

doc/build/changelog/changelog_11.rst
lib/sqlalchemy/dialects/postgresql/base.py
test/dialect/postgresql/test_types.py

index 81c80abb85b1501db78579b24c67f3ea9734cd81..6fbdf073084918b0f26d13789ef2fc7ee5de1bc8 100644 (file)
         amount of risk to compatibility w/ older or alternate Postgresql
         databases.
 
+    .. change:: 4006
+        :tags: bug, postgresql
+        :tickets: 4006
+        :versions: 1.2.0b1
+
+        Fixed bug where using :class:`.ARRAY` with a string type that
+        features a collation would fail to produce the correct syntax
+        within CREATE TABLE.
+
     .. change:: 3994
         :tags: bug, mssql
         :tickets: 3994
index 5f10ab9a9fa40e53f8156c72ba8751e875a5e5b6..7cb0ea7b0c4a3e6da8f03e50202dc5f01913f087 100644 (file)
@@ -1862,9 +1862,15 @@ class PGTypeCompiler(compiler.GenericTypeCompiler):
         return "BYTEA"
 
     def visit_ARRAY(self, type_, **kw):
-        return self.process(type_.item_type) + ('[]' * (type_.dimensions
-                                                        if type_.dimensions
-                                                        is not None else 1))
+
+        # TODO: pass **kw?
+        inner = self.process(type_.item_type)
+        return re.sub(
+            r'((?: COLLATE.*)?)$',
+            (r'[]\1' *
+             (type_.dimensions if type_.dimensions is not None else 1)),
+            inner
+        )
 
 
 class PGIdentifierPreparer(compiler.IdentifierPreparer):
index 807eeb60c42ac8eff4b6074ea42866ce83fb0614..8beedb8262318b1b00b2beefa31eb11e8e60aff6 100644 (file)
@@ -810,6 +810,18 @@ class TimePrecisionTest(fixtures.TestBase, AssertsCompiledSQL):
 class ArrayTest(AssertsCompiledSQL, fixtures.TestBase):
     __dialect__ = 'postgresql'
 
+    def test_array_type_render_str(self):
+        self.assert_compile(
+            postgresql.ARRAY(Unicode(30)),
+            "VARCHAR(30)[]"
+        )
+
+    def test_array_type_render_str_collate(self):
+        self.assert_compile(
+            postgresql.ARRAY(Unicode(30, collation="en_US")),
+            'VARCHAR(30)[] COLLATE "en_US"'
+        )
+
     def test_array_int_index(self):
         col = column('x', postgresql.ARRAY(Integer))
         self.assert_compile(
@@ -1043,6 +1055,17 @@ class ArrayRoundTripTest(fixtures.TablesTest, AssertsExecutionResults):
         assert isinstance(tbl.c.intarr.type.item_type, Integer)
         assert isinstance(tbl.c.strarr.type.item_type, String)
 
+    @testing.provide_metadata
+    def test_array_str_collation(self):
+        m = self.metadata
+
+        t = Table(
+            't', m, Column('data',
+                           sqltypes.ARRAY(String(50, collation="en_US")))
+        )
+
+        t.create()
+
     @testing.provide_metadata
     def test_array_agg(self):
         values_table = Table('values', self.metadata, Column('value', Integer))