From: Frazer McLean Date: Fri, 17 Jun 2016 16:55:11 +0000 (-0400) Subject: Support USING for Postgresql ALTER COLUMN. X-Git-Tag: rel_0_8_8~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=84b92980b051a0a22addd54abb64aedb4c2db396;p=thirdparty%2Fsqlalchemy%2Falembic.git Support USING for Postgresql ALTER COLUMN. Added support for the USING clause to the ALTER COLUMN operation for Postgresql. Support is via the :paramref:`.op.alter_column.postgresql_using` parameter. Fixes: #292 Change-Id: I8b1d418df0b6b731a68614dbffd7a9fb13de4de5 Pull-request: https://github.com/zzzeek/alembic/pull/27 --- diff --git a/alembic/ddl/postgresql.py b/alembic/ddl/postgresql.py index dd76639f..e8d8e2fb 100644 --- a/alembic/ddl/postgresql.py +++ b/alembic/ddl/postgresql.py @@ -2,10 +2,12 @@ import re from ..util import compat from .. import util -from .base import compiles, alter_table, format_table_name, RenameTable +from .base import compiles, alter_column, alter_table, format_table_name, \ + format_type, AlterColumn, RenameTable from .impl import DefaultImpl from sqlalchemy.dialects.postgresql import INTEGER, BIGINT from sqlalchemy import text, Numeric, Column +from sqlalchemy import types as sqltypes if compat.sqla_08: from sqlalchemy.sql.expression import UnaryExpression @@ -61,6 +63,49 @@ class PostgresqlImpl(DefaultImpl): ) ) + def alter_column(self, table_name, column_name, + nullable=None, + server_default=False, + name=None, + type_=None, + schema=None, + autoincrement=None, + existing_type=None, + existing_server_default=None, + existing_nullable=None, + existing_autoincrement=None, + **kw + ): + + using = kw.pop('postgresql_using', None) + + if using is not None and type_ is None: + raise util.CommandError( + "postgresql_using must be used with the type_ parameter") + + if type_ is not None: + self._exec(PostgresqlColumnType( + table_name, column_name, type_, schema=schema, + using=using, existing_type=existing_type, + existing_server_default=existing_server_default, + existing_nullable=existing_nullable, + )) + + super(PostgresqlImpl, self).alter_column( + table_name, column_name, + nullable=nullable, + server_default=server_default, + name=name, + schema=schema, + autoincrement=autoincrement, + existing_type=existing_type, + existing_server_default=existing_server_default, + existing_nullable=existing_nullable, + existing_autoincrement=existing_autoincrement, + **kw) + + + def autogen_column_reflect(self, inspector, table, column_info): if column_info.get('default') and \ isinstance(column_info['type'], (INTEGER, BIGINT)): @@ -125,9 +170,28 @@ class PostgresqlImpl(DefaultImpl): metadata_indexes.discard(idx) +class PostgresqlColumnType(AlterColumn): + + def __init__(self, name, column_name, type_, **kw): + using = kw.pop('using', None) + super(PostgresqlColumnType, self).__init__(name, column_name, **kw) + self.type_ = sqltypes.to_instance(type_) + self.using = using + + @compiles(RenameTable, "postgresql") def visit_rename_table(element, compiler, **kw): return "%s RENAME TO %s" % ( alter_table(compiler, element.table_name, element.schema), format_table_name(compiler, element.new_table_name, None) ) + + +@compiles(PostgresqlColumnType, "postgresql") +def visit_column_type(element, compiler, **kw): + return "%s %s %s %s" % ( + alter_table(compiler, element.table_name, element.schema), + alter_column(compiler, element.column_name), + "TYPE %s" % format_type(compiler, element.type_), + "USING %s" % element.using if element.using else "" + ) diff --git a/alembic/operations/ops.py b/alembic/operations/ops.py index dfa17ccc..f892227c 100644 --- a/alembic/operations/ops.py +++ b/alembic/operations/ops.py @@ -1397,6 +1397,12 @@ class AlterColumnOp(AlterTableOp): .. versionadded:: 0.7.0 'schema' can now accept a :class:`~sqlalchemy.sql.elements.quoted_name` construct. + :param postgresql_using: String argument which will indicate a + SQL expression to render within the Postgresql-specific USING clause + within ALTER COLUMN. + + .. versionadded:: 0.8.8 + """ alt = cls( diff --git a/docs/build/changelog.rst b/docs/build/changelog.rst index 118e39e0..ebd54fda 100644 --- a/docs/build/changelog.rst +++ b/docs/build/changelog.rst @@ -6,6 +6,15 @@ Changelog .. changelog:: :version: 0.8.8 + .. change:: + :tags: feature, operations, postgresql + :tickets: 292 + + Added support for the USING clause to the ALTER COLUMN operation + for Postgresql. Support is via the + :paramref:`.op.alter_column.postgresql_using` + parameter. Pull request courtesy Frazer McLean. + .. changelog:: :version: 0.8.7 :released: July 26, 2016 diff --git a/tests/test_postgresql.py b/tests/test_postgresql.py index 1724898f..d39df72b 100644 --- a/tests/test_postgresql.py +++ b/tests/test_postgresql.py @@ -59,6 +59,13 @@ class PostgresqlOpTest(TestBase): "CREATE INDEX geocoded ON locations (coordinates) " "WHERE locations.coordinates != Null") + def test_alter_column_type_using(self): + context = op_fixture('postgresql') + op.alter_column("t", "c", type_=Integer, postgresql_using='c::integer') + context.assert_( + 'ALTER TABLE t ALTER COLUMN c TYPE INTEGER USING c::integer' + ) + class PGOfflineEnumTest(TestBase): @@ -518,5 +525,3 @@ class PostgresqlDetectSerialTest(TestBase): None, Column('x', Integer, autoincrement=False, primary_key=True) ) - -