From 428dfeee48c1fc4ceb5712b8934e90132ee57e33 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 4 Jul 2016 16:37:26 -0400 Subject: [PATCH] Repair PG BIGSERIAL w/ TypeDecorator, Variant Some of the dialect impl memoization for TypeDecorator necessarily keeps the top-level TypeDecorator type around, since a user-defined type will have bind and result set processing behavior. For both TypeDecorator and Variant, PG dialect needs to ensure it's looking at the SQLAlchemy type to check for SmallInteger / BigInteger. Fixes: 3739 Change-Id: I2d45fb997f17c6272d6bb826a77d2dba665adae7 (cherry picked from commit 421fa6b8bf9f0c3c5041579c89ec405ce0f5e0b0) --- doc/build/changelog/changelog_10.rst | 10 ++++++++++ lib/sqlalchemy/dialects/postgresql/base.py | 3 +++ test/dialect/postgresql/test_dialect.py | 21 ++++++++++++++++++++- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/doc/build/changelog/changelog_10.rst b/doc/build/changelog/changelog_10.rst index a1e7d36789..7240e8e685 100644 --- a/doc/build/changelog/changelog_10.rst +++ b/doc/build/changelog/changelog_10.rst @@ -18,6 +18,16 @@ .. changelog:: :version: 1.0.14 + .. change:: + :tags: bug, postgresql + :tickets: 3739 + :versions: 1.1.0b3 + + Fixed bug whereby :class:`.TypeDecorator` and :class:`.Variant` + types were not deeply inspected enough by the Postgresql dialect + to determine if SMALLSERIAL or BIGSERIAL needed to be rendered + rather than SERIAL. + .. change:: :tags: bug, sql :tickets: 3735 diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py index 688ce9e1c5..cc0f890dc8 100644 --- a/lib/sqlalchemy/dialects/postgresql/base.py +++ b/lib/sqlalchemy/dialects/postgresql/base.py @@ -1484,6 +1484,9 @@ class PGDDLCompiler(compiler.DDLCompiler): colspec = self.preparer.format_column(column) impl_type = column.type.dialect_impl(self.dialect) + if isinstance(impl_type, sqltypes.TypeDecorator): + impl_type = impl_type.impl + if column.primary_key and \ column is column.table._autoincrement_column and \ ( diff --git a/test/dialect/postgresql/test_dialect.py b/test/dialect/postgresql/test_dialect.py index c0e1819d62..9f7af86387 100644 --- a/test/dialect/postgresql/test_dialect.py +++ b/test/dialect/postgresql/test_dialect.py @@ -8,7 +8,7 @@ from sqlalchemy import testing import datetime from sqlalchemy import ( Table, Column, select, MetaData, text, Integer, String, Sequence, Numeric, - DateTime, BigInteger, func, extract, SmallInteger) + DateTime, BigInteger, func, extract, SmallInteger, TypeDecorator) from sqlalchemy import exc, schema from sqlalchemy.dialects.postgresql import base as postgresql import logging @@ -252,6 +252,15 @@ class MiscTest(fixtures.TestBase, AssertsExecutionResults, AssertsCompiledSQL): "postgresql >= 8.2", "requires standard_conforming_strings") def test_serial_integer(self): + class BITD(TypeDecorator): + impl = Integer + + def load_dialect_impl(self, dialect): + if dialect.name == 'postgresql': + return BigInteger() + else: + return Integer() + for version, type_, expected in [ (None, Integer, 'SERIAL'), (None, BigInteger, 'BIGSERIAL'), @@ -259,6 +268,16 @@ class MiscTest(fixtures.TestBase, AssertsExecutionResults, AssertsCompiledSQL): ((9, 2), SmallInteger, 'SMALLSERIAL'), (None, postgresql.INTEGER, 'SERIAL'), (None, postgresql.BIGINT, 'BIGSERIAL'), + ( + None, Integer().with_variant(BigInteger(), 'postgresql'), + 'BIGSERIAL'), + ( + None, Integer().with_variant(postgresql.BIGINT, 'postgresql'), + 'BIGSERIAL'), + ( + (9, 2), Integer().with_variant(SmallInteger, 'postgresql'), + 'SMALLSERIAL'), + (None, BITD(), 'BIGSERIAL') ]: m = MetaData() -- 2.47.2