Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions alembic/ddl/postgresql.py
Original file line number Diff line number Diff line change
Expand Up @@ -569,8 +569,9 @@ def visit_identity_column(
# drop identity
text += "DROP IDENTITY"
return text
elif element.existing_server_default is None:
# add identity options
elif element.existing_server_default in (None, False):
# no known existing default (False is the "not specified"
# sentinel used by Operations.alter_column) - add identity options
text += "ADD "
text += compiler.visit_identity_column(element.default)
return text
Expand Down
13 changes: 13 additions & 0 deletions docs/build/unreleased/1504.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.. change::
:tags: bug, postgresql
:tickets: 1504

Fixed bug where :meth:`.Operations.alter_column` against a PostgreSQL
identity column would render an incomplete, invalid ``ALTER TABLE ...
ALTER COLUMN`` statement with no clause at all when
``existing_server_default`` was left at its default of not being
specified. The identity-column DDL compiler only recognized an explicit
``None`` as "no existing default", not the sentinel value used
internally by :meth:`.Operations.alter_column` when the argument is
omitted, so the "add identity" branch was skipped and no options were
ever rendered.
28 changes: 19 additions & 9 deletions tests/test_postgresql.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,21 +415,31 @@ def test_add_column_identity(self, kw, text):
)

@combinations(
({}, None),
(dict(always=True), None),
({}, None, True),
({}, None, False),
(dict(always=True), None, True),
(
dict(start=3, increment=33, maxvalue=99, cycle=True),
"INCREMENT BY 33 START WITH 3 MAXVALUE 99 CYCLE",
True,
),
)
def test_add_identity_to_column(self, kw, text):
def test_add_identity_to_column(
self, kw, text, pass_existing_server_default
):
context = op_fixture("postgresql")
op.alter_column(
"t1",
"some_column",
server_default=Identity(**kw),
existing_server_default=None,
)
alter_column_kw = {
"server_default": Identity(**kw),
}
if pass_existing_server_default:
alter_column_kw["existing_server_default"] = None
# else: leave existing_server_default at its default, which is the
# ``False`` "not specified" sentinel, not ``None``. It must be
# treated the same as an explicit ``None``, or the identity is
# never actually added.
# Regression test for
# https://github.com/sqlalchemy/alembic/issues/1504
op.alter_column("t1", "some_column", **alter_column_kw)
qualification = "ALWAYS" if kw.get("always", False) else "BY DEFAULT"
options = " (%s)" % text if text else ""
context.assert_(
Expand Down
Loading