From: Mike Bayer Date: Thu, 22 Jan 2026 16:15:35 +0000 (-0500) Subject: render PRIMARY KEY in add_column X-Git-Tag: rel_1_18_2~2^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ee9a8e9b1dd1245389303c0dcc5b7756e1104ac7;p=thirdparty%2Fsqlalchemy%2Falembic.git render PRIMARY KEY in add_column The ``primary_key`` parameter on :class:`.Column` is now honored when :meth:`.Operations.add_column` is used, and will emit the "PRIMARY KEY" keyword inline within the ADD COLUMN directive. This is strictly a syntax enhancement; no attempt is made to reconcile the column's primary key status with any existing primary key constraint or particular backend limitations on adding columns to the primary key. Fixes: #1232 Change-Id: I4a5bf163101ea045cd619daa6b780d6b89af79b3 --- diff --git a/alembic/ddl/base.py b/alembic/ddl/base.py index ad2847eb..9f93f87e 100644 --- a/alembic/ddl/base.py +++ b/alembic/ddl/base.py @@ -355,6 +355,9 @@ def add_column( compiler.get_column_specification(column, **kw), ) + if column.primary_key: + text += " PRIMARY KEY" + const = " ".join( compiler.process(constraint) for constraint in column.constraints ) diff --git a/alembic/op.pyi b/alembic/op.pyi index 96f68b82..5b7aad27 100644 --- a/alembic/op.pyi +++ b/alembic/op.pyi @@ -83,21 +83,16 @@ def add_column( .. note:: - With the exception of NOT NULL constraints or single-column FOREIGN - KEY constraints, other kinds of constraints such as PRIMARY KEY, - UNIQUE or CHECK constraints **cannot** be generated using this - method; for these constraints, refer to operations such as - :meth:`.Operations.create_primary_key` and - :meth:`.Operations.create_check_constraint`. In particular, the - following :class:`~sqlalchemy.schema.Column` parameters are - **ignored**: - - * :paramref:`~sqlalchemy.schema.Column.primary_key` - SQL databases - typically do not support an ALTER operation that can add - individual columns one at a time to an existing primary key - constraint, therefore it's less ambiguous to use the - :meth:`.Operations.create_primary_key` method, which assumes no - existing primary key constraint is present. + Not all contraint types may be indicated with this directive. + PRIMARY KEY, NOT NULL, FOREIGN KEY, and CHECK are honored, UNIQUE + is currently not. + + .. versionadded:: 1.18.2 Added support for PRIMARY KEY to be + emitted within :meth:`.Operations.add_column`. + + As of 1.18.2, the following :class:`~sqlalchemy.schema.Column` + parameters are **ignored**: + * :paramref:`~sqlalchemy.schema.Column.unique` - use the :meth:`.Operations.create_unique_constraint` method * :paramref:`~sqlalchemy.schema.Column.index` - use the diff --git a/alembic/operations/base.py b/alembic/operations/base.py index be3a77b2..f94cf280 100644 --- a/alembic/operations/base.py +++ b/alembic/operations/base.py @@ -650,21 +650,16 @@ class Operations(AbstractOperations): .. note:: - With the exception of NOT NULL constraints or single-column FOREIGN - KEY constraints, other kinds of constraints such as PRIMARY KEY, - UNIQUE or CHECK constraints **cannot** be generated using this - method; for these constraints, refer to operations such as - :meth:`.Operations.create_primary_key` and - :meth:`.Operations.create_check_constraint`. In particular, the - following :class:`~sqlalchemy.schema.Column` parameters are - **ignored**: - - * :paramref:`~sqlalchemy.schema.Column.primary_key` - SQL databases - typically do not support an ALTER operation that can add - individual columns one at a time to an existing primary key - constraint, therefore it's less ambiguous to use the - :meth:`.Operations.create_primary_key` method, which assumes no - existing primary key constraint is present. + Not all contraint types may be indicated with this directive. + PRIMARY KEY, NOT NULL, FOREIGN KEY, and CHECK are honored, UNIQUE + is currently not. + + .. versionadded:: 1.18.2 Added support for PRIMARY KEY to be + emitted within :meth:`.Operations.add_column`. + + As of 1.18.2, the following :class:`~sqlalchemy.schema.Column` + parameters are **ignored**: + * :paramref:`~sqlalchemy.schema.Column.unique` - use the :meth:`.Operations.create_unique_constraint` method * :paramref:`~sqlalchemy.schema.Column.index` - use the diff --git a/alembic/operations/ops.py b/alembic/operations/ops.py index c9b1526b..8e709283 100644 --- a/alembic/operations/ops.py +++ b/alembic/operations/ops.py @@ -2112,21 +2112,16 @@ class AddColumnOp(AlterTableOp): .. note:: - With the exception of NOT NULL constraints or single-column FOREIGN - KEY constraints, other kinds of constraints such as PRIMARY KEY, - UNIQUE or CHECK constraints **cannot** be generated using this - method; for these constraints, refer to operations such as - :meth:`.Operations.create_primary_key` and - :meth:`.Operations.create_check_constraint`. In particular, the - following :class:`~sqlalchemy.schema.Column` parameters are - **ignored**: - - * :paramref:`~sqlalchemy.schema.Column.primary_key` - SQL databases - typically do not support an ALTER operation that can add - individual columns one at a time to an existing primary key - constraint, therefore it's less ambiguous to use the - :meth:`.Operations.create_primary_key` method, which assumes no - existing primary key constraint is present. + Not all contraint types may be indicated with this directive. + PRIMARY KEY, NOT NULL, FOREIGN KEY, and CHECK are honored, UNIQUE + is currently not. + + .. versionadded:: 1.18.2 Added support for PRIMARY KEY to be + emitted within :meth:`.Operations.add_column`. + + As of 1.18.2, the following :class:`~sqlalchemy.schema.Column` + parameters are **ignored**: + * :paramref:`~sqlalchemy.schema.Column.unique` - use the :meth:`.Operations.create_unique_constraint` method * :paramref:`~sqlalchemy.schema.Column.index` - use the diff --git a/docs/build/unreleased/1232.rst b/docs/build/unreleased/1232.rst new file mode 100644 index 00000000..3fff7559 --- /dev/null +++ b/docs/build/unreleased/1232.rst @@ -0,0 +1,10 @@ +.. change:: + :tags: usecase, operations + :tickets: 1232 + + The ``primary_key`` parameter on :class:`.Column` is now honored when + :meth:`.Operations.add_column` is used, and will emit the "PRIMARY KEY" + keyword inline within the ADD COLUMN directive. This is strictly a syntax + enhancement; no attempt is made to reconcile the column's primary key + status with any existing primary key constraint or particular backend + limitations on adding columns to the primary key. diff --git a/tests/test_batch.py b/tests/test_batch.py index b1a2a623..bef3dc10 100644 --- a/tests/test_batch.py +++ b/tests/test_batch.py @@ -2291,7 +2291,6 @@ class BatchRoundTripMySQLTest(BatchRoundTripTest): def _datetime_server_default_fixture(self): return func.current_timestamp() - @exclusions.fails() def test_drop_pk_col_readd_pk_col(self): super().test_drop_pk_col_readd_pk_col() @@ -2348,7 +2347,6 @@ class BatchRoundTripPostgresqlTest(BatchRoundTripTest): def _datetime_server_default_fixture(self): return func.current_timestamp() - @exclusions.fails() def test_drop_pk_col_readd_pk_col(self): super().test_drop_pk_col_readd_pk_col() diff --git a/tests/test_op.py b/tests/test_op.py index f03024de..0b727f8b 100644 --- a/tests/test_op.py +++ b/tests/test_op.py @@ -71,6 +71,18 @@ class OpTest(TestBase): 'ALTER TABLE "some.schema".somename ADD COLUMN colname VARCHAR' ) + def test_add_column_primary_key(self): + context = op_fixture("postgresql") + op.add_column( + "somename", + Column("colname", String, primary_key=True), + ) + + context.assert_( + "ALTER TABLE somename ADD COLUMN colname " + "VARCHAR NOT NULL PRIMARY KEY" + ) + def test_rename_table_schema_hard_quoting(self): context = op_fixture("postgresql") op.rename_table( diff --git a/tests/test_postgresql.py b/tests/test_postgresql.py index db9aa382..fb20d170 100644 --- a/tests/test_postgresql.py +++ b/tests/test_postgresql.py @@ -188,7 +188,9 @@ class PostgresqlOpTest(TestBase): def test_col_w_pk_is_serial(self): context = op_fixture("postgresql") op.add_column("some_table", Column("q", Integer, primary_key=True)) - context.assert_("ALTER TABLE some_table ADD COLUMN q SERIAL NOT NULL") + context.assert_( + "ALTER TABLE some_table ADD COLUMN q SERIAL NOT NULL PRIMARY KEY" + ) def test_create_exclude_constraint(self): context = op_fixture("postgresql")